|
@@ -83,7 +83,7 @@ std::string PhpName(const std::string& full_name, bool is_descriptor);
|
|
std::string DefaultForField(FieldDescriptor* field);
|
|
std::string DefaultForField(FieldDescriptor* field);
|
|
std::string IntToString(int32 value);
|
|
std::string IntToString(int32 value);
|
|
std::string FilenameToClassname(const string& filename);
|
|
std::string FilenameToClassname(const string& filename);
|
|
-std::string GeneratedMetadataFileName(const std::string& proto_file,
|
|
|
|
|
|
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
|
|
bool is_descriptor);
|
|
bool is_descriptor);
|
|
std::string LabelForField(FieldDescriptor* field);
|
|
std::string LabelForField(FieldDescriptor* field);
|
|
std::string TypeName(FieldDescriptor* field);
|
|
std::string TypeName(FieldDescriptor* field);
|
|
@@ -94,6 +94,9 @@ void Indent(io::Printer* printer);
|
|
void Outdent(io::Printer* printer);
|
|
void Outdent(io::Printer* printer);
|
|
void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
|
|
void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
|
|
int is_descriptor);
|
|
int is_descriptor);
|
|
|
|
+void GenerateMessageConstructorDocComment(io::Printer* printer,
|
|
|
|
+ const Descriptor* message,
|
|
|
|
+ int is_descriptor);
|
|
void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
|
|
void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
|
|
int is_descriptor, int function_type);
|
|
int is_descriptor, int function_type);
|
|
void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
|
|
void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
|
|
@@ -105,31 +108,40 @@ void GenerateServiceDocComment(io::Printer* printer,
|
|
void GenerateServiceMethodDocComment(io::Printer* printer,
|
|
void GenerateServiceMethodDocComment(io::Printer* printer,
|
|
const MethodDescriptor* method);
|
|
const MethodDescriptor* method);
|
|
|
|
|
|
-std::string RenameEmpty(const std::string& name) {
|
|
|
|
- if (name == "Empty") {
|
|
|
|
- return "GPBEmpty";
|
|
|
|
- } else {
|
|
|
|
- return name;
|
|
|
|
|
|
+
|
|
|
|
+std::string ReservedNamePrefix(const string& classname,
|
|
|
|
+ const FileDescriptor* file) {
|
|
|
|
+ bool is_reserved = false;
|
|
|
|
+
|
|
|
|
+ string lower = classname;
|
|
|
|
+ transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < kReservedNamesSize; i++) {
|
|
|
|
+ if (lower == kReservedNames[i]) {
|
|
|
|
+ is_reserved = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
|
|
-std::string MessageFullName(const Descriptor* message, bool is_descriptor) {
|
|
|
|
- if (is_descriptor) {
|
|
|
|
- return StringReplace(message->full_name(),
|
|
|
|
- "google.protobuf",
|
|
|
|
- "google.protobuf.internal", false);
|
|
|
|
- } else {
|
|
|
|
- return message->full_name();
|
|
|
|
|
|
+ if (is_reserved) {
|
|
|
|
+ if (file->package() == "google.protobuf") {
|
|
|
|
+ return "GPB";
|
|
|
|
+ } else {
|
|
|
|
+ return "PB";
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return "";
|
|
}
|
|
}
|
|
|
|
|
|
-std::string EnumFullName(const EnumDescriptor* envm, bool is_descriptor) {
|
|
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
|
|
if (is_descriptor) {
|
|
if (is_descriptor) {
|
|
- return StringReplace(envm->full_name(),
|
|
|
|
|
|
+ return StringReplace(desc->full_name(),
|
|
"google.protobuf",
|
|
"google.protobuf",
|
|
"google.protobuf.internal", false);
|
|
"google.protobuf.internal", false);
|
|
} else {
|
|
} else {
|
|
- return envm->full_name();
|
|
|
|
|
|
+ return desc->full_name();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -141,22 +153,43 @@ std::string ClassNamePrefix(const string& classname,
|
|
return prefix;
|
|
return prefix;
|
|
}
|
|
}
|
|
|
|
|
|
- bool is_reserved = false;
|
|
|
|
|
|
+ return ReservedNamePrefix(classname, desc->file());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string GeneratedClassName(const DescriptorType* desc) {
|
|
|
|
+ std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
|
|
|
|
+ const Descriptor* containing = desc->containing_type();
|
|
|
|
+ while (containing != NULL) {
|
|
|
|
+ classname = ClassNamePrefix(containing->name(), desc) + containing->name()
|
|
|
|
+ + '\\' + classname;
|
|
|
|
+ containing = containing->containing_type();
|
|
|
|
+ }
|
|
|
|
+ return classname;
|
|
|
|
+}
|
|
|
|
|
|
|
|
+std::string GeneratedClassName(const ServiceDescriptor* desc) {
|
|
|
|
+ std::string classname = desc->name();
|
|
|
|
+ return ClassNamePrefix(classname, desc) + classname;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string LegacyGeneratedClassName(const DescriptorType* desc) {
|
|
|
|
+ std::string classname = desc->name();
|
|
|
|
+ const Descriptor* containing = desc->containing_type();
|
|
|
|
+ while (containing != NULL) {
|
|
|
|
+ classname = containing->name() + '_' + classname;
|
|
|
|
+ containing = containing->containing_type();
|
|
|
|
+ }
|
|
|
|
+ return ClassNamePrefix(classname, desc) + classname;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+std::string ClassNamePrefix(const string& classname) {
|
|
string lower = classname;
|
|
string lower = classname;
|
|
transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
|
transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
|
|
|
|
|
for (int i = 0; i < kReservedNamesSize; i++) {
|
|
for (int i = 0; i < kReservedNamesSize; i++) {
|
|
if (lower == kReservedNames[i]) {
|
|
if (lower == kReservedNames[i]) {
|
|
- is_reserved = true;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (is_reserved) {
|
|
|
|
- if (desc->file()->package() == "google.protobuf") {
|
|
|
|
- return "GPB";
|
|
|
|
- } else {
|
|
|
|
return "PB";
|
|
return "PB";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -192,34 +225,39 @@ std::string ConstantNamePrefix(const string& classname) {
|
|
}
|
|
}
|
|
|
|
|
|
template <typename DescriptorType>
|
|
template <typename DescriptorType>
|
|
-std::string NamespacedName(const string& classname,
|
|
|
|
- const DescriptorType* desc, bool is_descriptor) {
|
|
|
|
|
|
+std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
|
|
if (desc->file()->options().has_php_namespace()) {
|
|
if (desc->file()->options().has_php_namespace()) {
|
|
const string& php_namespace = desc->file()->options().php_namespace();
|
|
const string& php_namespace = desc->file()->options().php_namespace();
|
|
if (php_namespace != "") {
|
|
if (php_namespace != "") {
|
|
- return php_namespace + '\\' + classname;
|
|
|
|
- } else {
|
|
|
|
- return classname;
|
|
|
|
|
|
+ return php_namespace;
|
|
}
|
|
}
|
|
|
|
+ return "";
|
|
}
|
|
}
|
|
|
|
|
|
- if (desc->file()->package() == "") {
|
|
|
|
- return classname;
|
|
|
|
- } else {
|
|
|
|
- return PhpName(desc->file()->package(), is_descriptor) + '\\' +
|
|
|
|
- classname;
|
|
|
|
|
|
+ if (desc->file()->package() != "") {
|
|
|
|
+ return PhpName(desc->file()->package(), is_descriptor);
|
|
}
|
|
}
|
|
|
|
+ return "";
|
|
}
|
|
}
|
|
|
|
|
|
template <typename DescriptorType>
|
|
template <typename DescriptorType>
|
|
std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
|
|
std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
|
|
string classname = GeneratedClassName(desc);
|
|
string classname = GeneratedClassName(desc);
|
|
- return NamespacedName(classname, desc, is_descriptor);
|
|
|
|
|
|
+ string php_namespace = RootPhpNamespace(desc, is_descriptor);
|
|
|
|
+ if (php_namespace != "") {
|
|
|
|
+ return php_namespace + "\\" + classname;
|
|
|
|
+ }
|
|
|
|
+ return classname;
|
|
}
|
|
}
|
|
|
|
|
|
-std::string FullClassName(const ServiceDescriptor* desc, bool is_descriptor) {
|
|
|
|
- string classname = GeneratedClassName(desc);
|
|
|
|
- return NamespacedName(classname, desc, is_descriptor);
|
|
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
|
|
|
|
+ string classname = LegacyGeneratedClassName(desc);
|
|
|
|
+ string php_namespace = RootPhpNamespace(desc, is_descriptor);
|
|
|
|
+ if (php_namespace != "") {
|
|
|
|
+ return php_namespace + "\\" + classname;
|
|
|
|
+ }
|
|
|
|
+ return classname;
|
|
}
|
|
}
|
|
|
|
|
|
std::string PhpName(const std::string& full_name, bool is_descriptor) {
|
|
std::string PhpName(const std::string& full_name, bool is_descriptor) {
|
|
@@ -227,20 +265,23 @@ std::string PhpName(const std::string& full_name, bool is_descriptor) {
|
|
return kDescriptorPackageName;
|
|
return kDescriptorPackageName;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ std::string segment;
|
|
std::string result;
|
|
std::string result;
|
|
bool cap_next_letter = true;
|
|
bool cap_next_letter = true;
|
|
for (int i = 0; i < full_name.size(); i++) {
|
|
for (int i = 0; i < full_name.size(); i++) {
|
|
if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
|
|
if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
|
|
- result += full_name[i] + ('A' - 'a');
|
|
|
|
|
|
+ segment += full_name[i] + ('A' - 'a');
|
|
cap_next_letter = false;
|
|
cap_next_letter = false;
|
|
} else if (full_name[i] == '.') {
|
|
} else if (full_name[i] == '.') {
|
|
- result += '\\';
|
|
|
|
|
|
+ result += ClassNamePrefix(segment) + segment + '\\';
|
|
|
|
+ segment = "";
|
|
cap_next_letter = true;
|
|
cap_next_letter = true;
|
|
} else {
|
|
} else {
|
|
- result += full_name[i];
|
|
|
|
|
|
+ segment += full_name[i];
|
|
cap_next_letter = false;
|
|
cap_next_letter = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ result += ClassNamePrefix(segment) + segment;
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -268,11 +309,13 @@ std::string DefaultForField(const FieldDescriptor* field) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-std::string GeneratedMetadataFileName(const std::string& proto_file,
|
|
|
|
|
|
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
|
|
bool is_descriptor) {
|
|
bool is_descriptor) {
|
|
|
|
+ const string& proto_file = file->name();
|
|
int start_index = 0;
|
|
int start_index = 0;
|
|
int first_index = proto_file.find_first_of("/", start_index);
|
|
int first_index = proto_file.find_first_of("/", start_index);
|
|
- std::string result = "GPBMetadata/";
|
|
|
|
|
|
+ std::string result = "";
|
|
|
|
+ std::string segment = "";
|
|
|
|
|
|
if (proto_file == kEmptyFile) {
|
|
if (proto_file == kEmptyFile) {
|
|
return kEmptyMetadataFile;
|
|
return kEmptyMetadataFile;
|
|
@@ -290,24 +333,44 @@ std::string GeneratedMetadataFileName(const std::string& proto_file,
|
|
file_no_suffix = proto_file.substr(0, lastindex);
|
|
file_no_suffix = proto_file.substr(0, lastindex);
|
|
}
|
|
}
|
|
|
|
|
|
- while (first_index != string::npos) {
|
|
|
|
- result += UnderscoresToCamelCase(
|
|
|
|
- file_no_suffix.substr(start_index, first_index - start_index), true);
|
|
|
|
- result += "/";
|
|
|
|
- start_index = first_index + 1;
|
|
|
|
- first_index = file_no_suffix.find_first_of("/", start_index);
|
|
|
|
|
|
+ if (file->options().has_php_metadata_namespace()) {
|
|
|
|
+ const string& php_metadata_namespace =
|
|
|
|
+ file->options().php_metadata_namespace();
|
|
|
|
+ if (php_metadata_namespace != "" && php_metadata_namespace != "\\") {
|
|
|
|
+ result += php_metadata_namespace;
|
|
|
|
+ std::replace(result.begin(), result.end(), '\\', '/');
|
|
|
|
+ if (result.at(result.size() - 1) != '/') {
|
|
|
|
+ result += "/";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ result += "GPBMetadata/";
|
|
|
|
+ while (first_index != string::npos) {
|
|
|
|
+ segment = UnderscoresToCamelCase(
|
|
|
|
+ file_no_suffix.substr(start_index, first_index - start_index), true);
|
|
|
|
+ result += ReservedNamePrefix(segment, file) + segment + "/";
|
|
|
|
+ start_index = first_index + 1;
|
|
|
|
+ first_index = file_no_suffix.find_first_of("/", start_index);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Append file name.
|
|
// Append file name.
|
|
- result += RenameEmpty(UnderscoresToCamelCase(
|
|
|
|
- file_no_suffix.substr(start_index, first_index - start_index), true));
|
|
|
|
|
|
+ int file_name_start = file_no_suffix.find_last_of("/");
|
|
|
|
+ if (file_name_start == string::npos) {
|
|
|
|
+ file_name_start = 0;
|
|
|
|
+ } else {
|
|
|
|
+ file_name_start += 1;
|
|
|
|
+ }
|
|
|
|
+ segment = UnderscoresToCamelCase(
|
|
|
|
+ file_no_suffix.substr(file_name_start, first_index - file_name_start), true);
|
|
|
|
|
|
- return result += ".php";
|
|
|
|
|
|
+ return result + ReservedNamePrefix(segment, file) + segment + ".php";
|
|
}
|
|
}
|
|
|
|
|
|
-std::string GeneratedMessageFileName(const Descriptor* message,
|
|
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string GeneratedClassFileName(const DescriptorType* desc,
|
|
bool is_descriptor) {
|
|
bool is_descriptor) {
|
|
- std::string result = FullClassName(message, is_descriptor);
|
|
|
|
|
|
+ std::string result = FullClassName(desc, is_descriptor);
|
|
for (int i = 0; i < result.size(); i++) {
|
|
for (int i = 0; i < result.size(); i++) {
|
|
if (result[i] == '\\') {
|
|
if (result[i] == '\\') {
|
|
result[i] = '/';
|
|
result[i] = '/';
|
|
@@ -316,9 +379,11 @@ std::string GeneratedMessageFileName(const Descriptor* message,
|
|
return result + ".php";
|
|
return result + ".php";
|
|
}
|
|
}
|
|
|
|
|
|
-std::string GeneratedEnumFileName(const EnumDescriptor* en,
|
|
|
|
- bool is_descriptor) {
|
|
|
|
- std::string result = FullClassName(en, is_descriptor);
|
|
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
|
|
|
|
+ bool is_descriptor) {
|
|
|
|
+ std::string result = LegacyFullClassName(desc, is_descriptor);
|
|
|
|
+
|
|
for (int i = 0; i < result.size(); i++) {
|
|
for (int i = 0; i < result.size(); i++) {
|
|
if (result[i] == '\\') {
|
|
if (result[i] == '\\') {
|
|
result[i] = '/';
|
|
result[i] = '/';
|
|
@@ -461,10 +526,10 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor)
|
|
std::string EnumOrMessageSuffix(
|
|
std::string EnumOrMessageSuffix(
|
|
const FieldDescriptor* field, bool is_descriptor) {
|
|
const FieldDescriptor* field, bool is_descriptor) {
|
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
- return ", '" + MessageFullName(field->message_type(), is_descriptor) + "'";
|
|
|
|
|
|
+ return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
|
|
}
|
|
}
|
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
|
if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
|
- return ", '" + EnumFullName(field->enum_type(), is_descriptor) + "'";
|
|
|
|
|
|
+ return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
|
|
}
|
|
}
|
|
return "";
|
|
return "";
|
|
}
|
|
}
|
|
@@ -651,11 +716,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
|
printer->Print(
|
|
printer->Print(
|
|
"GPBUtil::checkMessage($var, \\^class_name^::class);\n",
|
|
"GPBUtil::checkMessage($var, \\^class_name^::class);\n",
|
|
- "class_name", FullClassName(field->message_type(), is_descriptor));
|
|
|
|
|
|
+ "class_name", LegacyFullClassName(field->message_type(), is_descriptor));
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
|
|
printer->Print(
|
|
printer->Print(
|
|
"GPBUtil::checkEnum($var, \\^class_name^::class);\n",
|
|
"GPBUtil::checkEnum($var, \\^class_name^::class);\n",
|
|
- "class_name", FullClassName(field->enum_type(), is_descriptor));
|
|
|
|
|
|
+ "class_name", LegacyFullClassName(field->enum_type(), is_descriptor));
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
|
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
|
printer->Print(
|
|
printer->Print(
|
|
"GPBUtil::checkString($var, ^utf8^);\n",
|
|
"GPBUtil::checkString($var, ^utf8^);\n",
|
|
@@ -711,7 +776,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
|
|
printer->Print(
|
|
printer->Print(
|
|
"$pool->addEnum('^name^', "
|
|
"$pool->addEnum('^name^', "
|
|
"\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
|
|
"\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
|
|
- "name", EnumFullName(en, true),
|
|
|
|
|
|
+ "name", DescriptorFullName(en, true),
|
|
"class_name", en->name());
|
|
"class_name", en->name());
|
|
Indent(printer);
|
|
Indent(printer);
|
|
|
|
|
|
@@ -743,13 +808,13 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
|
|
if (message->options().map_entry()) {
|
|
if (message->options().map_entry()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- string class_name = name_prefix.empty()?
|
|
|
|
- message->name() : name_prefix + "_" + message->name();
|
|
|
|
|
|
+ string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") +
|
|
|
|
+ ReservedNamePrefix(message->name(), message->file()) + message->name();
|
|
|
|
|
|
printer->Print(
|
|
printer->Print(
|
|
"$pool->addMessage('^message^', "
|
|
"$pool->addMessage('^message^', "
|
|
"\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
|
|
"\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
|
|
- "message", MessageFullName(message, true),
|
|
|
|
|
|
+ "message", DescriptorFullName(message, true),
|
|
"class_name", class_name);
|
|
"class_name", class_name);
|
|
|
|
|
|
Indent(printer);
|
|
Indent(printer);
|
|
@@ -851,7 +916,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
std::string dependency_filename =
|
|
std::string dependency_filename =
|
|
- GeneratedMetadataFileName(name, is_descriptor);
|
|
|
|
|
|
+ GeneratedMetadataFileName(file->dependency(i), is_descriptor);
|
|
printer->Print(
|
|
printer->Print(
|
|
"\\^name^::initOnce();\n",
|
|
"\\^name^::initOnce();\n",
|
|
"name", FilenameToClassname(dependency_filename));
|
|
"name", FilenameToClassname(dependency_filename));
|
|
@@ -945,7 +1010,7 @@ std::string FilenameToClassname(const string& filename) {
|
|
void GenerateMetadataFile(const FileDescriptor* file,
|
|
void GenerateMetadataFile(const FileDescriptor* file,
|
|
bool is_descriptor,
|
|
bool is_descriptor,
|
|
GeneratorContext* generator_context) {
|
|
GeneratorContext* generator_context) {
|
|
- std::string filename = GeneratedMetadataFileName(file->name(), is_descriptor);
|
|
|
|
|
|
+ std::string filename = GeneratedMetadataFileName(file, is_descriptor);
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
generator_context->Open(filename));
|
|
generator_context->Open(filename));
|
|
io::Printer printer(output.get(), '^');
|
|
io::Printer printer(output.get(), '^');
|
|
@@ -955,11 +1020,11 @@ void GenerateMetadataFile(const FileDescriptor* file,
|
|
std::string fullname = FilenameToClassname(filename);
|
|
std::string fullname = FilenameToClassname(filename);
|
|
int lastindex = fullname.find_last_of("\\");
|
|
int lastindex = fullname.find_last_of("\\");
|
|
|
|
|
|
- printer.Print(
|
|
|
|
- "namespace ^name^;\n\n",
|
|
|
|
- "name", fullname.substr(0, lastindex));
|
|
|
|
-
|
|
|
|
if (lastindex != string::npos) {
|
|
if (lastindex != string::npos) {
|
|
|
|
+ printer.Print(
|
|
|
|
+ "namespace ^name^;\n\n",
|
|
|
|
+ "name", fullname.substr(0, lastindex));
|
|
|
|
+
|
|
printer.Print(
|
|
printer.Print(
|
|
"class ^name^\n"
|
|
"class ^name^\n"
|
|
"{\n",
|
|
"{\n",
|
|
@@ -978,9 +1043,47 @@ void GenerateMetadataFile(const FileDescriptor* file,
|
|
printer.Print("}\n\n");
|
|
printer.Print("}\n\n");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+template <typename DescriptorType>
|
|
|
|
+void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
|
|
|
|
+ bool is_descriptor,
|
|
|
|
+ GeneratorContext* generator_context) {
|
|
|
|
+
|
|
|
|
+ std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
|
|
|
|
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
|
|
+ generator_context->Open(filename));
|
|
|
|
+ io::Printer printer(output.get(), '^');
|
|
|
|
+
|
|
|
|
+ GenerateHead(file, &printer);
|
|
|
|
+
|
|
|
|
+ std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
|
|
|
|
+ if (php_namespace != "") {
|
|
|
|
+ printer.Print(
|
|
|
|
+ "namespace ^name^;\n\n",
|
|
|
|
+ "name", php_namespace);
|
|
|
|
+ }
|
|
|
|
+ std::string newname = FullClassName(desc, is_descriptor);
|
|
|
|
+ printer.Print("if (false) {\n");
|
|
|
|
+ Indent(&printer);
|
|
|
|
+ printer.Print("/**\n");
|
|
|
|
+ printer.Print(" * This class is deprecated. Use ^new^ instead.\n",
|
|
|
|
+ "new", newname);
|
|
|
|
+ printer.Print(" * @deprecated\n");
|
|
|
|
+ printer.Print(" */\n");
|
|
|
|
+ printer.Print("class ^old^ {}\n",
|
|
|
|
+ "old", LegacyGeneratedClassName(desc));
|
|
|
|
+ Outdent(&printer);
|
|
|
|
+ printer.Print("}\n");
|
|
|
|
+ printer.Print("class_exists(^new^::class);\n",
|
|
|
|
+ "new", GeneratedClassName(desc));
|
|
|
|
+ printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
|
|
|
|
+ "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
|
|
|
|
+ "old", LegacyFullClassName(desc, is_descriptor),
|
|
|
|
+ "fullname", newname);
|
|
|
|
+}
|
|
|
|
+
|
|
void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
|
|
void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
|
|
bool is_descriptor, GeneratorContext* generator_context) {
|
|
bool is_descriptor, GeneratorContext* generator_context) {
|
|
- std::string filename = GeneratedEnumFileName(en, is_descriptor);
|
|
|
|
|
|
+ std::string filename = GeneratedClassFileName(en, is_descriptor);
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
generator_context->Open(filename));
|
|
generator_context->Open(filename));
|
|
io::Printer printer(output.get(), '^');
|
|
io::Printer printer(output.get(), '^');
|
|
@@ -990,32 +1093,22 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
|
|
std::string fullname = FilenameToClassname(filename);
|
|
std::string fullname = FilenameToClassname(filename);
|
|
int lastindex = fullname.find_last_of("\\");
|
|
int lastindex = fullname.find_last_of("\\");
|
|
|
|
|
|
- if (file->options().has_php_namespace()) {
|
|
|
|
- const string& php_namespace = file->options().php_namespace();
|
|
|
|
- if (!php_namespace.empty()) {
|
|
|
|
- printer.Print(
|
|
|
|
- "namespace ^name^;\n\n",
|
|
|
|
- "name", php_namespace);
|
|
|
|
- }
|
|
|
|
- } else if (!file->package().empty()) {
|
|
|
|
|
|
+ if (lastindex != string::npos) {
|
|
printer.Print(
|
|
printer.Print(
|
|
"namespace ^name^;\n\n",
|
|
"namespace ^name^;\n\n",
|
|
"name", fullname.substr(0, lastindex));
|
|
"name", fullname.substr(0, lastindex));
|
|
}
|
|
}
|
|
|
|
|
|
- GenerateEnumDocComment(&printer, en, is_descriptor);
|
|
|
|
-
|
|
|
|
if (lastindex != string::npos) {
|
|
if (lastindex != string::npos) {
|
|
- printer.Print(
|
|
|
|
- "class ^name^\n"
|
|
|
|
- "{\n",
|
|
|
|
- "name", fullname.substr(lastindex + 1));
|
|
|
|
- } else {
|
|
|
|
- printer.Print(
|
|
|
|
- "class ^name^\n"
|
|
|
|
- "{\n",
|
|
|
|
- "name", fullname);
|
|
|
|
|
|
+ fullname = fullname.substr(lastindex + 1);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ GenerateEnumDocComment(&printer, en, is_descriptor);
|
|
|
|
+
|
|
|
|
+ printer.Print(
|
|
|
|
+ "class ^name^\n"
|
|
|
|
+ "{\n",
|
|
|
|
+ "name", fullname);
|
|
Indent(&printer);
|
|
Indent(&printer);
|
|
|
|
|
|
for (int i = 0; i < en->value_count(); i++) {
|
|
for (int i = 0; i < en->value_count(); i++) {
|
|
@@ -1028,6 +1121,17 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
|
|
|
|
|
|
Outdent(&printer);
|
|
Outdent(&printer);
|
|
printer.Print("}\n\n");
|
|
printer.Print("}\n\n");
|
|
|
|
+
|
|
|
|
+ // write legacy file for backwards compatiblity with nested messages and enums
|
|
|
|
+ if (en->containing_type() != NULL) {
|
|
|
|
+ printer.Print(
|
|
|
|
+ "// Adding a class alias for backwards compatibility with the previous class name.\n");
|
|
|
|
+ printer.Print(
|
|
|
|
+ "class_alias(^new^::class, \\^old^::class);\n\n",
|
|
|
|
+ "new", fullname,
|
|
|
|
+ "old", LegacyFullClassName(en, is_descriptor));
|
|
|
|
+ LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
@@ -1039,7 +1143,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- std::string filename = GeneratedMessageFileName(message, is_descriptor);
|
|
|
|
|
|
+ std::string filename = GeneratedClassFileName(message, is_descriptor);
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
std::unique_ptr<io::ZeroCopyOutputStream> output(
|
|
generator_context->Open(filename));
|
|
generator_context->Open(filename));
|
|
io::Printer printer(output.get(), '^');
|
|
io::Printer printer(output.get(), '^');
|
|
@@ -1049,14 +1153,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
std::string fullname = FilenameToClassname(filename);
|
|
std::string fullname = FilenameToClassname(filename);
|
|
int lastindex = fullname.find_last_of("\\");
|
|
int lastindex = fullname.find_last_of("\\");
|
|
|
|
|
|
- if (file->options().has_php_namespace()) {
|
|
|
|
- const string& php_namespace = file->options().php_namespace();
|
|
|
|
- if (!php_namespace.empty()) {
|
|
|
|
- printer.Print(
|
|
|
|
- "namespace ^name^;\n\n",
|
|
|
|
- "name", php_namespace);
|
|
|
|
- }
|
|
|
|
- } else if (!file->package().empty()) {
|
|
|
|
|
|
+ if (lastindex != string::npos) {
|
|
printer.Print(
|
|
printer.Print(
|
|
"namespace ^name^;\n\n",
|
|
"namespace ^name^;\n\n",
|
|
"name", fullname.substr(0, lastindex));
|
|
"name", fullname.substr(0, lastindex));
|
|
@@ -1066,16 +1163,13 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
|
|
|
|
GenerateMessageDocComment(&printer, message, is_descriptor);
|
|
GenerateMessageDocComment(&printer, message, is_descriptor);
|
|
if (lastindex != string::npos) {
|
|
if (lastindex != string::npos) {
|
|
- printer.Print(
|
|
|
|
- "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
|
|
|
|
- "{\n",
|
|
|
|
- "name", fullname.substr(lastindex + 1));
|
|
|
|
- } else {
|
|
|
|
- printer.Print(
|
|
|
|
- "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
|
|
|
|
- "{\n",
|
|
|
|
- "name", fullname);
|
|
|
|
|
|
+ fullname = fullname.substr(lastindex + 1);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ printer.Print(
|
|
|
|
+ "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
|
|
|
|
+ "{\n",
|
|
|
|
+ "name", fullname);
|
|
Indent(&printer);
|
|
Indent(&printer);
|
|
|
|
|
|
// Field and oneof definitions.
|
|
// Field and oneof definitions.
|
|
@@ -1089,16 +1183,17 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
}
|
|
}
|
|
printer.Print("\n");
|
|
printer.Print("\n");
|
|
|
|
|
|
|
|
+ GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
|
|
printer.Print(
|
|
printer.Print(
|
|
- "public function __construct() {\n");
|
|
|
|
|
|
+ "public function __construct($data = NULL) {\n");
|
|
Indent(&printer);
|
|
Indent(&printer);
|
|
|
|
|
|
std::string metadata_filename =
|
|
std::string metadata_filename =
|
|
- GeneratedMetadataFileName(file->name(), is_descriptor);
|
|
|
|
|
|
+ GeneratedMetadataFileName(file, is_descriptor);
|
|
std::string metadata_fullname = FilenameToClassname(metadata_filename);
|
|
std::string metadata_fullname = FilenameToClassname(metadata_filename);
|
|
printer.Print(
|
|
printer.Print(
|
|
"\\^fullname^::initOnce();\n"
|
|
"\\^fullname^::initOnce();\n"
|
|
- "parent::__construct();\n",
|
|
|
|
|
|
+ "parent::__construct($data);\n",
|
|
"fullname", metadata_fullname);
|
|
"fullname", metadata_fullname);
|
|
|
|
|
|
Outdent(&printer);
|
|
Outdent(&printer);
|
|
@@ -1126,6 +1221,17 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
|
|
Outdent(&printer);
|
|
Outdent(&printer);
|
|
printer.Print("}\n\n");
|
|
printer.Print("}\n\n");
|
|
|
|
|
|
|
|
+ // write legacy file for backwards compatiblity with nested messages and enums
|
|
|
|
+ if (message->containing_type() != NULL) {
|
|
|
|
+ printer.Print(
|
|
|
|
+ "// Adding a class alias for backwards compatibility with the previous class name.\n");
|
|
|
|
+ printer.Print(
|
|
|
|
+ "class_alias(^new^::class, \\^old^::class);\n\n",
|
|
|
|
+ "new", fullname,
|
|
|
|
+ "old", LegacyFullClassName(message, is_descriptor));
|
|
|
|
+ LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
|
|
|
|
+ }
|
|
|
|
+
|
|
// Nested messages and enums.
|
|
// Nested messages and enums.
|
|
for (int i = 0; i < message->nested_type_count(); i++) {
|
|
for (int i = 0; i < message->nested_type_count(); i++) {
|
|
GenerateMessageFile(file, message->nested_type(i), is_descriptor,
|
|
GenerateMessageFile(file, message->nested_type(i), is_descriptor,
|
|
@@ -1150,14 +1256,9 @@ void GenerateServiceFile(const FileDescriptor* file,
|
|
std::string fullname = FilenameToClassname(filename);
|
|
std::string fullname = FilenameToClassname(filename);
|
|
int lastindex = fullname.find_last_of("\\");
|
|
int lastindex = fullname.find_last_of("\\");
|
|
|
|
|
|
- if (file->options().has_php_namespace()) {
|
|
|
|
- const string& php_namespace = file->options().php_namespace();
|
|
|
|
- if (!php_namespace.empty()) {
|
|
|
|
- printer.Print(
|
|
|
|
- "namespace ^name^;\n\n",
|
|
|
|
- "name", php_namespace);
|
|
|
|
- }
|
|
|
|
- } else if (!file->package().empty()) {
|
|
|
|
|
|
+ if (!file->options().php_namespace().empty() ||
|
|
|
|
+ (!file->options().has_php_namespace() && !file->package().empty()) ||
|
|
|
|
+ lastindex != string::npos) {
|
|
printer.Print(
|
|
printer.Print(
|
|
"namespace ^name^;\n\n",
|
|
"namespace ^name^;\n\n",
|
|
"name", fullname.substr(0, lastindex));
|
|
"name", fullname.substr(0, lastindex));
|
|
@@ -1251,7 +1352,8 @@ static string EscapePhpdoc(const string& input) {
|
|
}
|
|
}
|
|
|
|
|
|
static void GenerateDocCommentBodyForLocation(
|
|
static void GenerateDocCommentBodyForLocation(
|
|
- io::Printer* printer, const SourceLocation& location) {
|
|
|
|
|
|
+ io::Printer* printer, const SourceLocation& location, bool trailingNewline,
|
|
|
|
+ int indentCount) {
|
|
string comments = location.leading_comments.empty() ?
|
|
string comments = location.leading_comments.empty() ?
|
|
location.trailing_comments : location.leading_comments;
|
|
location.trailing_comments : location.leading_comments;
|
|
if (!comments.empty()) {
|
|
if (!comments.empty()) {
|
|
@@ -1272,14 +1374,16 @@ static void GenerateDocCommentBodyForLocation(
|
|
// Most lines should start with a space. Watch out for lines that start
|
|
// Most lines should start with a space. Watch out for lines that start
|
|
// with a /, since putting that right after the leading asterisk will
|
|
// with a /, since putting that right after the leading asterisk will
|
|
// close the comment.
|
|
// close the comment.
|
|
- if (!lines[i].empty() && lines[i][0] == '/') {
|
|
|
|
|
|
+ if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') {
|
|
printer->Print(" * ^line^\n", "line", lines[i]);
|
|
printer->Print(" * ^line^\n", "line", lines[i]);
|
|
} else {
|
|
} else {
|
|
- printer->Print(" *^line^\n", "line", lines[i]);
|
|
|
|
|
|
+ std::string indent = std::string(indentCount, ' ');
|
|
|
|
+ printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- printer->Print(
|
|
|
|
- " *\n");
|
|
|
|
|
|
+ if (trailingNewline) {
|
|
|
|
+ printer->Print(" *\n");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1288,7 +1392,7 @@ static void GenerateDocCommentBody(
|
|
io::Printer* printer, const DescriptorType* descriptor) {
|
|
io::Printer* printer, const DescriptorType* descriptor) {
|
|
SourceLocation location;
|
|
SourceLocation location;
|
|
if (descriptor->GetSourceLocation(&location)) {
|
|
if (descriptor->GetSourceLocation(&location)) {
|
|
- GenerateDocCommentBodyForLocation(printer, location);
|
|
|
|
|
|
+ GenerateDocCommentBodyForLocation(printer, location, true, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1310,10 +1414,41 @@ void GenerateMessageDocComment(io::Printer* printer,
|
|
printer->Print(
|
|
printer->Print(
|
|
" * Generated from protobuf message <code>^messagename^</code>\n"
|
|
" * Generated from protobuf message <code>^messagename^</code>\n"
|
|
" */\n",
|
|
" */\n",
|
|
- "fullname", EscapePhpdoc(PhpName(message->full_name(), is_descriptor)),
|
|
|
|
|
|
+ "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
|
|
"messagename", EscapePhpdoc(message->full_name()));
|
|
"messagename", EscapePhpdoc(message->full_name()));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void GenerateMessageConstructorDocComment(io::Printer* printer,
|
|
|
|
+ const Descriptor* message,
|
|
|
|
+ int is_descriptor) {
|
|
|
|
+ // In theory we should have slightly different comments for setters, getters,
|
|
|
|
+ // etc., but in practice everyone already knows the difference between these
|
|
|
|
+ // so it's redundant information.
|
|
|
|
+
|
|
|
|
+ // We start the comment with the main body based on the comments from the
|
|
|
|
+ // .proto file (if present). We then end with the field declaration, e.g.:
|
|
|
|
+ // optional string foo = 5;
|
|
|
|
+ // If the field is a group, the debug string might end with {.
|
|
|
|
+ printer->Print("/**\n");
|
|
|
|
+ printer->Print(" * Constructor.\n");
|
|
|
|
+ printer->Print(" *\n");
|
|
|
|
+ printer->Print(" * @param array $data {\n");
|
|
|
|
+ printer->Print(" * Optional. Data for populating the Message object.\n");
|
|
|
|
+ printer->Print(" *\n");
|
|
|
|
+ for (int i = 0; i < message->field_count(); i++) {
|
|
|
|
+ const FieldDescriptor* field = message->field(i);
|
|
|
|
+ printer->Print(" * @type ^php_type^ $^var^\n",
|
|
|
|
+ "php_type", PhpSetterTypeName(field, is_descriptor),
|
|
|
|
+ "var", field->name());
|
|
|
|
+ SourceLocation location;
|
|
|
|
+ if (field->GetSourceLocation(&location)) {
|
|
|
|
+ GenerateDocCommentBodyForLocation(printer, location, false, 10);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ printer->Print(" * }\n");
|
|
|
|
+ printer->Print(" */\n");
|
|
|
|
+}
|
|
|
|
+
|
|
void GenerateServiceDocComment(io::Printer* printer,
|
|
void GenerateServiceDocComment(io::Printer* printer,
|
|
const ServiceDescriptor* service) {
|
|
const ServiceDescriptor* service) {
|
|
printer->Print("/**\n");
|
|
printer->Print("/**\n");
|
|
@@ -1355,9 +1490,9 @@ void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
|
|
printer->Print("/**\n");
|
|
printer->Print("/**\n");
|
|
GenerateDocCommentBody(printer, enum_);
|
|
GenerateDocCommentBody(printer, enum_);
|
|
printer->Print(
|
|
printer->Print(
|
|
- " * Protobuf enum <code>^fullname^</code>\n"
|
|
|
|
|
|
+ " * Protobuf type <code>^fullname^</code>\n"
|
|
" */\n",
|
|
" */\n",
|
|
- "fullname", EscapePhpdoc(PhpName(enum_->full_name(), is_descriptor)));
|
|
|
|
|
|
+ "fullname", EscapePhpdoc(enum_->full_name()));
|
|
}
|
|
}
|
|
|
|
|
|
void GenerateEnumValueDocComment(io::Printer* printer,
|
|
void GenerateEnumValueDocComment(io::Printer* printer,
|
|
@@ -1410,31 +1545,6 @@ bool Generator::Generate(const FileDescriptor* file, const string& parameter,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-std::string GeneratedClassName(const Descriptor* desc) {
|
|
|
|
- std::string classname = desc->name();
|
|
|
|
- const Descriptor* containing = desc->containing_type();
|
|
|
|
- while (containing != NULL) {
|
|
|
|
- classname = containing->name() + '_' + classname;
|
|
|
|
- containing = containing->containing_type();
|
|
|
|
- }
|
|
|
|
- return ClassNamePrefix(classname, desc) + classname;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-std::string GeneratedClassName(const EnumDescriptor* desc) {
|
|
|
|
- std::string classname = desc->name();
|
|
|
|
- const Descriptor* containing = desc->containing_type();
|
|
|
|
- while (containing != NULL) {
|
|
|
|
- classname = containing->name() + '_' + classname;
|
|
|
|
- containing = containing->containing_type();
|
|
|
|
- }
|
|
|
|
- return ClassNamePrefix(classname, desc) + classname;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-std::string GeneratedClassName(const ServiceDescriptor* desc) {
|
|
|
|
- std::string classname = desc->name();
|
|
|
|
- return ClassNamePrefix(classname, desc) + classname;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
} // namespace php
|
|
} // namespace php
|
|
} // namespace compiler
|
|
} // namespace compiler
|
|
} // namespace protobuf
|
|
} // namespace protobuf
|