dep-protobuf/upb_generator/reflection/header.cc
Joshua Haberman 3f145ee0b5 Replace Output with io::Printer in upb's reflection code generator.
Note that the code has grown a lot in terms of line count -- the original codegen was less than 200 lines, where this refactored version is more than 300 lines.  But hopefully it has also gotten more readable and easier to maintain.  Feedback welcome about whether it has achieved this goal.

PiperOrigin-RevId: 738968810
2025-03-20 15:57:41 -07:00

98 lines
2.9 KiB
C++

// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// Generates foo.upbdefs.h.
#include <string>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/io/printer.h"
#include "upb/reflection/def.hpp"
#include "upb_generator/common/names.h"
#include "upb_generator/file_layout.h"
#include "upb_generator/reflection/context.h"
#include "upb_generator/reflection/names.h"
namespace upb::generator::reflection {
namespace {
using Sub = google::protobuf::io::Printer::Sub;
void GenerateMessageDefAccessor(upb::MessageDefPtr d, Context& ctx) {
ctx.Emit(
{{"def_init_symbol", ReflectionFileSymbol(d.file().name())},
{"full_name", d.full_name()},
{"get_message_symbol", ReflectionGetMessageSymbol(d.full_name())}},
R"cc(
UPB_INLINE const upb_MessageDef *$get_message_symbol$(upb_DefPool *s) {
_upb_DefPool_LoadDefInit(s, &$def_init_symbol$);
return upb_DefPool_FindMessageByName(s, "$full_name$");
}
)cc");
}
void WriteMessages(upb::FileDefPtr file, Context& ctx) {
for (auto msg : SortedMessages(file)) {
GenerateMessageDefAccessor(msg, ctx);
ctx.Emit("\n");
}
}
void WriteDefHeader(upb::FileDefPtr file, Context& ctx) {
ctx.Emit(
{
{"def_init_symbol", ReflectionFileSymbol(file.name())},
{"dllexport_decl", ctx.options().dllexport_decl},
{"file_warning", FileWarning(file.name())},
{"include_guard", IncludeGuard(file.name())},
Sub("messages", [&] { WriteMessages(file, ctx); }).WithSuffix(";"),
},
R"(
$file_warning$
#ifndef $include_guard$_UPBDEFS_H_
#define $include_guard$_UPBDEFS_H_
#include "upb/reflection/def.h"
#include "upb/reflection/internal/def_pool.h"
#include "upb/port/def.inc"
#ifdef __cplusplus
extern "C" {
#endif
extern$ dllexport_decl$ _upb_DefPool_Init $def_init_symbol$;
$messages$;
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port/undef.inc"
#endif /* $include_guard$_UPBDEFS_H_ */
)");
}
} // namespace
std::string DefHeaderFilename(upb::FileDefPtr file) {
return absl::StrCat(StripExtension(file.name()), ".upbdefs.h");
}
void GenerateReflectionHeader(upb::FileDefPtr file, const Options& options,
google::protobuf::compiler::GeneratorContext* context) {
Context h_context(options, context->Open(DefHeaderFilename(file)));
WriteDefHeader(file, h_context);
}
} // namespace upb::generator::reflection