[lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).
This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).
Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 08:23:27 +01:00
|
|
|
//===-- StructuredData.cpp ------------------------------------------------===//
|
2014-06-13 02:37:02 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2014-06-13 02:37:02 +00:00
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2017-06-27 10:45:31 +00:00
|
|
|
#include "lldb/Utility/StructuredData.h"
|
2017-03-22 18:40:07 +00:00
|
|
|
#include "lldb/Utility/FileSpec.h"
|
2017-05-12 04:51:55 +00:00
|
|
|
#include "lldb/Utility/Status.h"
|
2023-06-17 13:18:23 +01:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2017-11-17 03:28:58 +00:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2017-06-27 10:45:31 +00:00
|
|
|
#include <cerrno>
|
2021-05-26 12:19:37 +02:00
|
|
|
#include <cinttypes>
|
2017-06-27 10:45:31 +00:00
|
|
|
#include <cstdlib>
|
2015-03-17 20:04:04 +00:00
|
|
|
|
2014-06-13 02:37:02 +00:00
|
|
|
using namespace lldb_private;
|
2019-10-01 17:41:48 +00:00
|
|
|
using namespace llvm;
|
2014-06-13 02:37:02 +00:00
|
|
|
|
2019-10-01 17:41:52 +00:00
|
|
|
static StructuredData::ObjectSP ParseJSONValue(json::Value &value);
|
|
|
|
|
static StructuredData::ObjectSP ParseJSONObject(json::Object *object);
|
|
|
|
|
static StructuredData::ObjectSP ParseJSONArray(json::Array *array);
|
|
|
|
|
|
2023-04-17 16:11:07 -07:00
|
|
|
StructuredData::ObjectSP StructuredData::ParseJSON(llvm::StringRef json_text) {
|
2019-10-01 17:41:52 +00:00
|
|
|
llvm::Expected<json::Value> value = json::parse(json_text);
|
|
|
|
|
if (!value) {
|
|
|
|
|
llvm::consumeError(value.takeError());
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return ParseJSONValue(*value);
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2016-09-14 19:07:35 +00:00
|
|
|
StructuredData::ObjectSP
|
2017-05-12 04:51:55 +00:00
|
|
|
StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) {
|
2016-09-12 23:10:56 +00:00
|
|
|
StructuredData::ObjectSP return_sp;
|
|
|
|
|
|
2017-06-27 10:45:31 +00:00
|
|
|
auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath());
|
|
|
|
|
if (!buffer_or_error) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormatv(
|
|
|
|
|
"could not open input file: {0} - {1}.", input_spec.GetPath(),
|
|
|
|
|
buffer_or_error.getError().message());
|
2016-09-12 23:10:56 +00:00
|
|
|
return return_sp;
|
|
|
|
|
}
|
2020-08-17 17:21:52 -07:00
|
|
|
llvm::Expected<json::Value> value =
|
|
|
|
|
json::parse(buffer_or_error.get()->getBuffer().str());
|
|
|
|
|
if (value)
|
|
|
|
|
return ParseJSONValue(*value);
|
2024-09-05 12:19:31 -07:00
|
|
|
error = Status::FromError(value.takeError());
|
2020-08-17 17:21:52 -07:00
|
|
|
return StructuredData::ObjectSP();
|
2016-09-12 23:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
2022-11-03 11:25:40 -07:00
|
|
|
bool StructuredData::IsRecordType(const ObjectSP object_sp) {
|
|
|
|
|
return object_sp->GetType() == lldb::eStructuredDataTypeArray ||
|
|
|
|
|
object_sp->GetType() == lldb::eStructuredDataTypeDictionary;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:52 +00:00
|
|
|
static StructuredData::ObjectSP ParseJSONValue(json::Value &value) {
|
|
|
|
|
if (json::Object *O = value.getAsObject())
|
|
|
|
|
return ParseJSONObject(O);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2019-10-01 17:41:52 +00:00
|
|
|
if (json::Array *A = value.getAsArray())
|
|
|
|
|
return ParseJSONArray(A);
|
2014-06-13 02:37:02 +00:00
|
|
|
|
[JSON] Add error reporting to fromJSON and ObjectMapper
Translating between JSON objects and C++ strutctures is common.
From experience in clangd, fromJSON/ObjectMapper work well and save a lot of
code, but aren't adopted elsewhere at least partly due to total lack of error
reporting beyond "ok"/"bad".
The recently-added error model should be rich enough for most applications.
It requires tracking the path within the root object and reporting local
errors at appropriate places.
To do this, we exploit the fact that the call graph of recursive
parse functions mirror the structure of the JSON itself.
The current path is represented as a linked list of segments, each of which is
on the stack as a parameter. Concretely, fromJSON now looks like:
bool fromJSON(const Value&, T&, Path);
Beyond the signature change, this is reasonably unobtrusive: building
the path segments is mostly handled by ObjectMapper and the vector<T> fromJSON.
However the root caller of fromJSON must now create a Root object to
store the errors, which is a little clunky.
I've added high-level parse<T>(StringRef) -> Expected<T>, but it's not
general enough to be the primary interface I think (at least, not usable in
clangd).
All existing users (mostly just clangd) are updated in this patch,
making this change backwards-compatible is a bit hairy.
Differential Revision: https://reviews.llvm.org/D88103
2020-09-24 01:14:12 +02:00
|
|
|
if (auto s = value.getAsString())
|
|
|
|
|
return std::make_shared<StructuredData::String>(*s);
|
2019-10-01 17:41:52 +00:00
|
|
|
|
[JSON] Add error reporting to fromJSON and ObjectMapper
Translating between JSON objects and C++ strutctures is common.
From experience in clangd, fromJSON/ObjectMapper work well and save a lot of
code, but aren't adopted elsewhere at least partly due to total lack of error
reporting beyond "ok"/"bad".
The recently-added error model should be rich enough for most applications.
It requires tracking the path within the root object and reporting local
errors at appropriate places.
To do this, we exploit the fact that the call graph of recursive
parse functions mirror the structure of the JSON itself.
The current path is represented as a linked list of segments, each of which is
on the stack as a parameter. Concretely, fromJSON now looks like:
bool fromJSON(const Value&, T&, Path);
Beyond the signature change, this is reasonably unobtrusive: building
the path segments is mostly handled by ObjectMapper and the vector<T> fromJSON.
However the root caller of fromJSON must now create a Root object to
store the errors, which is a little clunky.
I've added high-level parse<T>(StringRef) -> Expected<T>, but it's not
general enough to be the primary interface I think (at least, not usable in
clangd).
All existing users (mostly just clangd) are updated in this patch,
making this change backwards-compatible is a bit hairy.
Differential Revision: https://reviews.llvm.org/D88103
2020-09-24 01:14:12 +02:00
|
|
|
if (auto b = value.getAsBoolean())
|
|
|
|
|
return std::make_shared<StructuredData::Boolean>(*b);
|
2019-10-01 17:41:52 +00:00
|
|
|
|
2023-02-16 18:17:59 -08:00
|
|
|
if (auto u = value.getAsUINT64())
|
2023-05-22 13:52:09 -07:00
|
|
|
return std::make_shared<StructuredData::UnsignedInteger>(*u);
|
2023-02-16 18:17:59 -08:00
|
|
|
|
2020-09-24 01:30:42 +02:00
|
|
|
if (auto i = value.getAsInteger())
|
2023-05-22 13:52:09 -07:00
|
|
|
return std::make_shared<StructuredData::SignedInteger>(*i);
|
2019-10-01 17:41:52 +00:00
|
|
|
|
[JSON] Add error reporting to fromJSON and ObjectMapper
Translating between JSON objects and C++ strutctures is common.
From experience in clangd, fromJSON/ObjectMapper work well and save a lot of
code, but aren't adopted elsewhere at least partly due to total lack of error
reporting beyond "ok"/"bad".
The recently-added error model should be rich enough for most applications.
It requires tracking the path within the root object and reporting local
errors at appropriate places.
To do this, we exploit the fact that the call graph of recursive
parse functions mirror the structure of the JSON itself.
The current path is represented as a linked list of segments, each of which is
on the stack as a parameter. Concretely, fromJSON now looks like:
bool fromJSON(const Value&, T&, Path);
Beyond the signature change, this is reasonably unobtrusive: building
the path segments is mostly handled by ObjectMapper and the vector<T> fromJSON.
However the root caller of fromJSON must now create a Root object to
store the errors, which is a little clunky.
I've added high-level parse<T>(StringRef) -> Expected<T>, but it's not
general enough to be the primary interface I think (at least, not usable in
clangd).
All existing users (mostly just clangd) are updated in this patch,
making this change backwards-compatible is a bit hairy.
Differential Revision: https://reviews.llvm.org/D88103
2020-09-24 01:14:12 +02:00
|
|
|
if (auto d = value.getAsNumber())
|
|
|
|
|
return std::make_shared<StructuredData::Float>(*d);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-10-10 13:45:45 -07:00
|
|
|
if (auto n = value.getAsNull())
|
|
|
|
|
return std::make_shared<StructuredData::Null>();
|
|
|
|
|
|
2015-07-06 23:40:40 +00:00
|
|
|
return StructuredData::ObjectSP();
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-06-13 02:37:02 +00:00
|
|
|
|
2019-10-01 17:41:52 +00:00
|
|
|
static StructuredData::ObjectSP ParseJSONObject(json::Object *object) {
|
|
|
|
|
auto dict_up = std::make_unique<StructuredData::Dictionary>();
|
|
|
|
|
for (auto &KV : *object) {
|
|
|
|
|
StringRef key = KV.first;
|
|
|
|
|
json::Value value = KV.second;
|
|
|
|
|
if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
|
|
|
|
|
dict_up->AddItem(key, value_sp);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2020-01-13 18:23:39 -08:00
|
|
|
return std::move(dict_up);
|
2015-07-06 23:40:40 +00:00
|
|
|
}
|
2014-06-13 02:37:02 +00:00
|
|
|
|
2019-10-01 17:41:52 +00:00
|
|
|
static StructuredData::ObjectSP ParseJSONArray(json::Array *array) {
|
|
|
|
|
auto array_up = std::make_unique<StructuredData::Array>();
|
|
|
|
|
for (json::Value &value : *array) {
|
|
|
|
|
if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
|
|
|
|
|
array_up->AddItem(value_sp);
|
|
|
|
|
}
|
2020-01-13 18:23:39 -08:00
|
|
|
return std::move(array_up);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StructuredData::ObjectSP
|
|
|
|
|
StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
|
2023-07-05 11:18:23 -07:00
|
|
|
if (GetType() == lldb::eStructuredDataTypeDictionary) {
|
2014-06-13 02:37:02 +00:00
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
|
2023-07-05 11:18:23 -07:00
|
|
|
llvm::StringRef key = match.first;
|
|
|
|
|
ObjectSP value = GetAsDictionary()->GetValueForKey(key);
|
|
|
|
|
if (!value)
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
// Do we have additional words to descend? If not, return the value
|
|
|
|
|
// we're at right now.
|
|
|
|
|
if (match.second.empty())
|
|
|
|
|
return value;
|
|
|
|
|
|
|
|
|
|
return value->GetObjectForDotSeparatedPath(match.second);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-06-13 02:37:02 +00:00
|
|
|
|
2023-07-05 11:18:23 -07:00
|
|
|
if (GetType() == lldb::eStructuredDataTypeArray) {
|
2014-06-13 02:37:02 +00:00
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
|
2023-07-05 11:18:23 -07:00
|
|
|
if (match.second.empty())
|
|
|
|
|
return shared_from_this();
|
|
|
|
|
|
|
|
|
|
uint64_t val = 0;
|
|
|
|
|
if (!llvm::to_integer(match.second, val, /* Base = */ 10))
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
return GetAsArray()->GetItemAtIndex(val);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-06-13 02:37:02 +00:00
|
|
|
|
2023-07-05 11:18:23 -07:00
|
|
|
return shared_from_this();
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2016-07-20 03:49:02 +00:00
|
|
|
void StructuredData::Object::DumpToStdout(bool pretty_print) const {
|
2019-10-01 17:41:48 +00:00
|
|
|
json::OStream stream(llvm::outs(), pretty_print ? 2 : 0);
|
|
|
|
|
Serialize(stream);
|
2015-03-17 20:04:04 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Array::Serialize(json::OStream &s) const {
|
|
|
|
|
s.arrayBegin();
|
2015-05-27 03:23:26 +00:00
|
|
|
for (const auto &item_sp : m_items) {
|
2019-10-01 17:41:48 +00:00
|
|
|
item_sp->Serialize(s);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
2019-10-01 17:41:48 +00:00
|
|
|
s.arrayEnd();
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Float::Serialize(json::OStream &s) const {
|
|
|
|
|
s.value(m_value);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Boolean::Serialize(json::OStream &s) const {
|
|
|
|
|
s.value(m_value);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::String::Serialize(json::OStream &s) const {
|
|
|
|
|
s.value(m_value);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Dictionary::Serialize(json::OStream &s) const {
|
|
|
|
|
s.objectBegin();
|
2023-08-29 17:22:48 -07:00
|
|
|
|
|
|
|
|
// To ensure the output format is always stable, we sort the dictionary by key
|
|
|
|
|
// first.
|
|
|
|
|
using Entry = std::pair<llvm::StringRef, ObjectSP>;
|
|
|
|
|
std::vector<Entry> sorted_entries;
|
|
|
|
|
for (const auto &pair : m_dict)
|
|
|
|
|
sorted_entries.push_back({pair.first(), pair.second});
|
|
|
|
|
|
|
|
|
|
llvm::sort(sorted_entries);
|
|
|
|
|
|
|
|
|
|
for (const auto &pair : sorted_entries) {
|
|
|
|
|
s.attributeBegin(pair.first);
|
2019-10-01 17:41:48 +00:00
|
|
|
pair.second->Serialize(s);
|
|
|
|
|
s.attributeEnd();
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
2019-10-01 17:41:48 +00:00
|
|
|
s.objectEnd();
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Null::Serialize(json::OStream &s) const {
|
|
|
|
|
s.value(nullptr);
|
2014-06-13 02:37:02 +00:00
|
|
|
}
|
2015-03-17 20:04:04 +00:00
|
|
|
|
2019-10-01 17:41:48 +00:00
|
|
|
void StructuredData::Generic::Serialize(json::OStream &s) const {
|
|
|
|
|
s.value(llvm::formatv("{0:X}", m_object));
|
2015-03-17 20:04:04 +00:00
|
|
|
}
|
2022-11-03 11:25:40 -07:00
|
|
|
|
|
|
|
|
void StructuredData::Float::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
s.Printf("%f", m_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::Boolean::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
s.Printf(m_value ? "True" : "False");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::String::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
s.Printf("%s", m_value.empty() ? "\"\"" : m_value.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::Array::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
size_t indentation_level = s.GetIndentLevel();
|
|
|
|
|
for (const auto &item_sp : m_items) {
|
|
|
|
|
// Sanitize.
|
|
|
|
|
if (!item_sp)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Reset original indentation level.
|
|
|
|
|
s.SetIndentLevel(indentation_level);
|
|
|
|
|
s.Indent();
|
|
|
|
|
|
|
|
|
|
// Print key
|
|
|
|
|
s.Printf("[%zu]:", index++);
|
|
|
|
|
|
|
|
|
|
// Return to new line and increase indentation if value is record type.
|
|
|
|
|
// Otherwise add spacing.
|
|
|
|
|
bool should_indent = IsRecordType(item_sp);
|
|
|
|
|
if (should_indent) {
|
|
|
|
|
s.EOL();
|
|
|
|
|
s.IndentMore();
|
|
|
|
|
} else {
|
|
|
|
|
s.PutChar(' ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print value and new line if now last pair.
|
|
|
|
|
item_sp->GetDescription(s);
|
|
|
|
|
if (item_sp != *(--m_items.end()))
|
|
|
|
|
s.EOL();
|
|
|
|
|
|
|
|
|
|
// Reset indentation level if it was incremented previously.
|
|
|
|
|
if (should_indent)
|
|
|
|
|
s.IndentLess();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
size_t indentation_level = s.GetIndentLevel();
|
2023-08-29 17:22:48 -07:00
|
|
|
|
|
|
|
|
// To ensure the output format is always stable, we sort the dictionary by key
|
|
|
|
|
// first.
|
|
|
|
|
using Entry = std::pair<llvm::StringRef, ObjectSP>;
|
|
|
|
|
std::vector<Entry> sorted_entries;
|
|
|
|
|
for (const auto &pair : m_dict)
|
|
|
|
|
sorted_entries.push_back({pair.first(), pair.second});
|
|
|
|
|
|
|
|
|
|
llvm::sort(sorted_entries);
|
|
|
|
|
|
|
|
|
|
for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
|
|
|
|
|
iter++) {
|
2022-11-03 11:25:40 -07:00
|
|
|
// Sanitize.
|
2023-08-29 17:22:48 -07:00
|
|
|
if (iter->first.empty() || !iter->second)
|
2022-11-03 11:25:40 -07:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Reset original indentation level.
|
|
|
|
|
s.SetIndentLevel(indentation_level);
|
|
|
|
|
s.Indent();
|
|
|
|
|
|
|
|
|
|
// Print key.
|
2023-08-29 17:22:48 -07:00
|
|
|
s.Format("{0}:", iter->first);
|
2022-11-03 11:25:40 -07:00
|
|
|
|
|
|
|
|
// Return to new line and increase indentation if value is record type.
|
|
|
|
|
// Otherwise add spacing.
|
2023-08-29 17:00:59 -07:00
|
|
|
bool should_indent = IsRecordType(iter->second);
|
2022-11-03 11:25:40 -07:00
|
|
|
if (should_indent) {
|
|
|
|
|
s.EOL();
|
|
|
|
|
s.IndentMore();
|
|
|
|
|
} else {
|
|
|
|
|
s.PutChar(' ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print value and new line if now last pair.
|
2023-08-29 17:00:59 -07:00
|
|
|
iter->second->GetDescription(s);
|
2023-08-29 17:22:48 -07:00
|
|
|
if (std::next(iter) != sorted_entries.end())
|
2022-11-03 11:25:40 -07:00
|
|
|
s.EOL();
|
|
|
|
|
|
|
|
|
|
// Reset indentation level if it was incremented previously.
|
|
|
|
|
if (should_indent)
|
|
|
|
|
s.IndentLess();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::Null::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
s.Printf("NULL");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StructuredData::Generic::GetDescription(lldb_private::Stream &s) const {
|
|
|
|
|
s.Printf("%p", m_object);
|
|
|
|
|
}
|