-
Notifications
You must be signed in to change notification settings - Fork 15.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an RAII namespace printer helper for C++ codegen.
This can be used to open and close namespace automatically within generated C++ code. PiperOrigin-RevId: 618930720
- Loading branch information
1 parent
6f1ef6f
commit 8599ab5
Showing
4 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#include "google/protobuf/compiler/cpp/namespace_printer.h" | ||
|
||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "absl/log/die_if_null.h" | ||
#include "absl/strings/substitute.h" | ||
#include "google/protobuf/io/printer.h" | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace compiler { | ||
namespace cpp { | ||
|
||
NamespacePrinter::NamespacePrinter( | ||
google::protobuf::io::Printer* const p, std::vector<std::string> namespace_components) | ||
: p_(ABSL_DIE_IF_NULL(p)), | ||
namespace_components_(std::move(namespace_components)) { | ||
// Open the namespace. | ||
for (const std::string& ns : namespace_components_) { | ||
p_->Print(absl::Substitute("namespace $0 {\n", ns)); | ||
} | ||
p_->Print("\n"); | ||
} | ||
|
||
NamespacePrinter::~NamespacePrinter() { | ||
// Close the namespace. | ||
for (const std::string& ns : namespace_components_) { | ||
p_->Print(absl::Substitute("} // namespace $0\n", ns)); | ||
} | ||
} | ||
|
||
} // namespace cpp | ||
} // namespace compiler | ||
} // namespace protobuf | ||
} // namespace google |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Protocol Buffers - Google's data interchange format | ||
// Copyright 2024 Google Inc. 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 | ||
|
||
// An RAII type for printing a namespace. | ||
// | ||
// Example: | ||
// { | ||
// Printer printer(output_stream.get(), '$'); | ||
// const NamespacePrinter namespace_printer(&printer, {"a", "b", "c"}); | ||
// // namespace opening will be opened here | ||
// ... | ||
// // namespace closing will be emitted here | ||
// } | ||
// | ||
// By default, the filename will be converted to a macro by substituting '/' and | ||
// '.' characters with '_'. If a different transformation is required, an | ||
// optional transformation function can be provided. | ||
|
||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMESPACE_PRINTER_H__ | ||
#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMESPACE_PRINTER_H__ | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "google/protobuf/io/printer.h" | ||
|
||
// Must be included last. | ||
#include "google/protobuf/port_def.inc" | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace compiler { | ||
namespace cpp { | ||
|
||
// An RAII type for printing a namespace. | ||
class PROTOC_EXPORT NamespacePrinter final { | ||
public: | ||
explicit NamespacePrinter(google::protobuf::io::Printer* p, | ||
std::vector<std::string> namespace_components); | ||
~NamespacePrinter(); | ||
|
||
private: | ||
google::protobuf::io::Printer* const p_; | ||
const std::vector<std::string> namespace_components_; | ||
}; | ||
|
||
#include "google/protobuf/port_undef.inc" | ||
|
||
} // namespace cpp | ||
} // namespace compiler | ||
} // namespace protobuf | ||
} // namespace google | ||
|
||
#endif // GOOGLE_PROTOBUF_COMPILER_CPP_NAMESPACE_PRINTER_H__ |
78 changes: 78 additions & 0 deletions
78
src/google/protobuf/compiler/cpp/namespace_printer_unittest.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include "google/protobuf/compiler/cpp/namespace_printer.h" | ||
|
||
#include <string> | ||
|
||
#include <gtest/gtest.h> | ||
#include "absl/log/absl_check.h" | ||
#include "absl/strings/string_view.h" | ||
#include "absl/types/optional.h" | ||
#include "google/protobuf/io/printer.h" | ||
#include "google/protobuf/io/zero_copy_stream.h" | ||
#include "google/protobuf/io/zero_copy_stream_impl_lite.h" | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace compiler { | ||
namespace cpp { | ||
|
||
namespace { | ||
|
||
class NamespacePrinterTest : public testing::Test { | ||
protected: | ||
io::ZeroCopyOutputStream* output() { | ||
ABSL_CHECK(stream_.has_value()); | ||
return &*stream_; | ||
} | ||
absl::string_view written() { | ||
stream_.reset(); | ||
return out_; | ||
} | ||
|
||
std::string out_; | ||
absl::optional<io::StringOutputStream> stream_{&out_}; | ||
}; | ||
|
||
TEST_F(NamespacePrinterTest, Basic) { | ||
{ | ||
io::Printer printer(output(), '$'); | ||
|
||
const NamespacePrinter namespace_printer(&printer, {"A", "B", "E"}); | ||
|
||
EXPECT_FALSE(printer.failed()); | ||
} | ||
|
||
EXPECT_EQ(written(), | ||
"namespace A {\n" | ||
"namespace B {\n" | ||
"namespace E {\n" | ||
"\n" | ||
"} // namespace A\n" | ||
"} // namespace B\n" | ||
"} // namespace E\n"); | ||
} | ||
|
||
TEST_F(NamespacePrinterTest, DifferentDelim) { | ||
{ | ||
io::Printer printer(output(), '\0'); | ||
|
||
const NamespacePrinter namespace_printer(&printer, {"A", "B", "E"}); | ||
|
||
EXPECT_FALSE(printer.failed()); | ||
} | ||
|
||
EXPECT_EQ(written(), | ||
"namespace A {\n" | ||
"namespace B {\n" | ||
"namespace E {\n" | ||
"\n" | ||
"} // namespace A\n" | ||
"} // namespace B\n" | ||
"} // namespace E\n"); | ||
} | ||
|
||
} // namespace | ||
|
||
} // namespace cpp | ||
} // namespace compiler | ||
} // namespace protobuf | ||
} // namespace google |