blob: faf61748bf42e43fa30e59fd95bf2e14a38cb493 [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/console/format_async_task.h"
#include "src/developer/debug/zxdb/client/async_task.h"
#include "src/developer/debug/zxdb/client/async_task_tree.h"
#include "src/developer/debug/zxdb/console/format_location.h"
#include "src/developer/debug/zxdb/format/format_name.h"
#include "src/developer/debug/zxdb/format/string_util.h"
namespace zxdb {
namespace {
constexpr std::string kAwaiteeMarker = "└─ ";
} // namespace
fxl::RefPtr<AsyncOutputBuffer> FormatAsyncTask(const AsyncTask& task, const TargetSymbols* symbols,
const FormatTaskOptions& options,
const fxl::RefPtr<EvalContext>& eval_context,
int indent) {
auto out = fxl::MakeRefCounted<AsyncOutputBuffer>();
if (indent >= options.indent_amount) {
out->Append(std::string(indent - options.indent_amount, ' '));
out->Append(kAwaiteeMarker);
} else {
out->Append(std::string(indent, ' '));
}
switch (task.GetType()) {
case AsyncTask::Type::kFunction: {
out->Append(FormatIdentifier(task.GetIdentifier(), {}));
if (!task.GetState().empty()) {
out->Append(" (");
out->Append(Syntax::kComment, task.GetState());
out->Append(")");
}
if (task.GetLocation().is_valid()) {
out->Append(" " + GetBullet() + " ");
out->Append(FormatFileLine(task.GetLocation().file_line(), symbols));
}
break;
}
case AsyncTask::Type::kScope:
// The Scope's "identifier" is the literal word "Scope" these are bolded.
out->Append(Syntax::kStringBold, task.GetIdentifier().GetFullNameNoQual());
// Unnamed scopes are allowed.
if (!task.GetState().empty()) {
out->Append("(\"");
out->Append(Syntax::kComment, task.GetState());
out->Append("\")");
}
break;
case AsyncTask::Type::kTask:
[[fallthrough]];
case AsyncTask::Type::kFuture:
out->Append(FormatIdentifier(task.GetIdentifier(), {}));
// These usually have some form of unique identifier associated with them.
out->Append("(");
out->Append(Syntax::kStringDim, task.GetState());
out->Append(")");
break;
case AsyncTask::Type::kOther:
// For types of tasks that we don't have other handlers for, we treat the "identifier" as a
// literal string which doesn't go through the FormatIdentifier context..
out->Append(task.GetIdentifier().GetFullNameNoQual());
if (!task.GetState().empty()) {
out->Append("(");
out->Append(Syntax::kStringDim, task.GetState());
out->Append(")");
}
break;
}
out->Append("\n");
if (options.verbose) {
for (const auto& value : task.GetValues()) {
out->Append(std::string(indent + options.variable_indent_amount, ' '));
out->Append(
FormatValue(value.value, options.variable, eval_context, value.name ? *value.name : ""));
out->Append("\n");
}
}
out->Complete();
return out;
}
fxl::RefPtr<AsyncOutputBuffer> FormatAsyncTaskTree(const AsyncTaskTree& tree,
const TargetSymbols* symbols,
const FormatTaskOptions& options,
const fxl::RefPtr<EvalContext>& eval_context) {
auto out = fxl::MakeRefCounted<AsyncOutputBuffer>();
if (!tree.has_tasks()) {
out->Append(Syntax::kComment, "No async tasks found.\n");
out->Complete();
return out;
}
tree.ForEach([&, out](const AsyncTaskTree::TaskEntry& entry) {
out->Append(FormatAsyncTask(entry.task, symbols, options, eval_context,
entry.depth * options.indent_amount));
});
out->Complete();
return out;
}
} // namespace zxdb