223 lines
6.2 KiB
C++
223 lines
6.2 KiB
C++
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "tools/proto_merger/proto_file_serializer.h"
|
|
|
|
#include "perfetto/ext/base/string_utils.h"
|
|
|
|
namespace perfetto {
|
|
namespace proto_merger {
|
|
namespace {
|
|
|
|
std::string DeletedComment(const std::string& prefix) {
|
|
std::string output;
|
|
output += "\n";
|
|
output += prefix + " //\n";
|
|
output += prefix;
|
|
output +=
|
|
" // The following enums/messages/fields are not present upstream\n";
|
|
output += prefix + " //\n";
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeComments(const std::string& prefix,
|
|
const std::vector<std::string>& lines) {
|
|
std::string output;
|
|
for (const auto& line : lines) {
|
|
output.append(prefix);
|
|
output.append("//");
|
|
output.append(line);
|
|
output.append("\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeLeadingComments(const std::string& prefix,
|
|
const ProtoFile::Member& member,
|
|
bool prefix_newline_if_comment = true) {
|
|
if (member.leading_comments.empty())
|
|
return "";
|
|
|
|
std::string output;
|
|
if (prefix_newline_if_comment) {
|
|
output += "\n";
|
|
}
|
|
output += SerializeComments(prefix, member.leading_comments);
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeTrailingComments(const std::string& prefix,
|
|
const ProtoFile::Member& member) {
|
|
return SerializeComments(prefix, member.trailing_comments);
|
|
}
|
|
|
|
std::string SerializeOptions(const std::vector<ProtoFile::Option>& options) {
|
|
if (options.empty())
|
|
return "";
|
|
|
|
std::string output;
|
|
output += " [";
|
|
for (const auto& option : options) {
|
|
output += option.key + " = " + option.value;
|
|
}
|
|
output += "]";
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeEnumValue(size_t indent,
|
|
const ProtoFile::Enum::Value& value) {
|
|
std::string prefix(indent * 2, ' ');
|
|
|
|
std::string output;
|
|
output += SerializeLeadingComments(prefix, value, false);
|
|
|
|
output += prefix + value.name + " = " + std::to_string(value.number);
|
|
output += SerializeOptions(value.options);
|
|
output += ";\n";
|
|
|
|
output += SerializeTrailingComments(prefix, value);
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeEnum(size_t indent, const ProtoFile::Enum& en) {
|
|
std::string prefix(indent * 2, ' ');
|
|
++indent;
|
|
|
|
std::string output;
|
|
output += SerializeLeadingComments(prefix, en);
|
|
|
|
output += prefix + "enum " + en.name + " {\n";
|
|
for (const auto& value : en.values) {
|
|
output += SerializeEnumValue(indent, value);
|
|
}
|
|
output += prefix + "}\n";
|
|
|
|
output += SerializeTrailingComments(prefix, en);
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeField(size_t indent,
|
|
const ProtoFile::Field& field,
|
|
bool write_label) {
|
|
std::string prefix(indent * 2, ' ');
|
|
|
|
std::string output;
|
|
output += SerializeLeadingComments(prefix, field);
|
|
|
|
std::string label;
|
|
if (write_label) {
|
|
label = field.label + " ";
|
|
}
|
|
output += prefix + label + field.type + " " + field.name + " = " +
|
|
std::to_string(field.number);
|
|
|
|
output += SerializeOptions(field.options);
|
|
output += ";\n";
|
|
|
|
output += SerializeTrailingComments(prefix, field);
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeOneof(size_t indent, const ProtoFile::Oneof& oneof) {
|
|
std::string prefix(indent * 2, ' ');
|
|
++indent;
|
|
|
|
std::string output;
|
|
output += SerializeLeadingComments(prefix, oneof);
|
|
|
|
output += prefix + "oneof " + oneof.name + " {\n";
|
|
for (const auto& field : oneof.fields) {
|
|
output += SerializeField(indent, field, false);
|
|
}
|
|
output += prefix + "}\n";
|
|
|
|
output += SerializeTrailingComments(prefix, oneof);
|
|
return output;
|
|
}
|
|
|
|
std::string SerializeMessage(size_t indent, const ProtoFile::Message& message) {
|
|
std::string prefix(indent * 2, ' ');
|
|
++indent;
|
|
|
|
std::string output;
|
|
output += SerializeLeadingComments(prefix, message);
|
|
|
|
output += prefix + "message " + message.name + " {\n";
|
|
for (const auto& en : message.enums) {
|
|
output += SerializeEnum(indent, en);
|
|
}
|
|
for (const auto& nested : message.nested_messages) {
|
|
output += SerializeMessage(indent, nested);
|
|
}
|
|
for (const auto& oneof : message.oneofs) {
|
|
output += SerializeOneof(indent, oneof);
|
|
}
|
|
for (const auto& field : message.fields) {
|
|
output += SerializeField(indent, field, true);
|
|
}
|
|
|
|
if (!message.deleted_enums.empty() || !message.deleted_fields.empty() ||
|
|
!message.deleted_nested_messages.empty() ||
|
|
!message.deleted_oneofs.empty()) {
|
|
output += DeletedComment(prefix);
|
|
for (const auto& en : message.deleted_enums) {
|
|
output += SerializeEnum(indent, en);
|
|
}
|
|
for (const auto& nested : message.deleted_nested_messages) {
|
|
output += SerializeMessage(indent, nested);
|
|
}
|
|
for (const auto& oneof : message.deleted_oneofs) {
|
|
output += SerializeOneof(indent, oneof);
|
|
}
|
|
for (const auto& field : message.deleted_fields) {
|
|
output += SerializeField(indent, field, true);
|
|
}
|
|
}
|
|
|
|
output += prefix + "}\n";
|
|
|
|
output += SerializeTrailingComments(prefix, message);
|
|
return output;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::string ProtoFileToDotProto(const ProtoFile& proto_file) {
|
|
std::string output;
|
|
for (const auto& en : proto_file.enums) {
|
|
output += SerializeEnum(0, en);
|
|
}
|
|
for (const auto& message : proto_file.messages) {
|
|
output += SerializeMessage(0, message);
|
|
}
|
|
|
|
if (!proto_file.deleted_enums.empty() ||
|
|
!proto_file.deleted_messages.empty()) {
|
|
output += DeletedComment("");
|
|
|
|
for (const auto& en : proto_file.deleted_enums) {
|
|
output += SerializeEnum(0, en);
|
|
}
|
|
for (const auto& nested : proto_file.deleted_messages) {
|
|
output += SerializeMessage(0, nested);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
} // namespace proto_merger
|
|
} // namespace perfetto
|