From 437ec356fbe15d8737d797505aafb8e2b2629e7b Mon Sep 17 00:00:00 2001 From: "Philip K. Warren" Date: Mon, 11 Sep 2023 13:18:27 -0700 Subject: [PATCH] Update Kotlin compiler to escape package names (#13310) The current Kotlin code generator creates code which fails to compile with imports like: ``` syntax = "proto3"; package net.example.v1; message Sample { string net = 1; } ``` This results in a condition where 'net' is ambiguous in some cases (could refer to the field or the package). To avoid these issues, the code generator should enclose package paths in backticks: ``` net.example.v1.SampleKt => `net.example.v1`.SampleKt ``` Fixes #13182. Closes #13310 COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/13310 from pkwarren:pkw/issue-13182 3f72b2f1e129d13462935d651498ea45f59fc776 PiperOrigin-RevId: 564481691 --- src/google/protobuf/compiler/java/message.cc | 3 +-- src/google/protobuf/compiler/java/message_lite.cc | 6 +++--- .../protobuf/compiler/java/name_resolver.cc | 15 +++++++++++++++ src/google/protobuf/compiler/java/name_resolver.h | 1 + 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/google/protobuf/compiler/java/message.cc b/src/google/protobuf/compiler/java/message.cc index 257e69c302..c530b66ce5 100644 --- a/src/google/protobuf/compiler/java/message.cc +++ b/src/google/protobuf/compiler/java/message.cc @@ -1316,8 +1316,7 @@ void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers( "message", EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), "message_kt", - EscapeKotlinKeywords( - name_resolver_->GetKotlinExtensionsClassName(descriptor_))); + name_resolver_->GetKotlinExtensionsClassNameEscaped(descriptor_)); for (int i = 0; i < descriptor_->nested_type_count(); i++) { if (IsMapEntry(descriptor_->nested_type(i))) continue; diff --git a/src/google/protobuf/compiler/java/message_lite.cc b/src/google/protobuf/compiler/java/message_lite.cc index 9668e15786..ac4a15cbd0 100644 --- a/src/google/protobuf/compiler/java/message_lite.cc +++ b/src/google/protobuf/compiler/java/message_lite.cc @@ -841,8 +841,7 @@ void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers( "message", EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), "message_kt", - EscapeKotlinKeywords( - name_resolver_->GetKotlinExtensionsClassName(descriptor_))); + name_resolver_->GetKotlinExtensionsClassNameEscaped(descriptor_)); for (int i = 0; i < descriptor_->nested_type_count(); i++) { if (IsMapEntry(descriptor_->nested_type(i))) continue; @@ -853,7 +852,8 @@ void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers( GenerateKotlinOrNull(printer); } -void ImmutableMessageLiteGenerator::GenerateKotlinOrNull(io::Printer* printer) const { +void ImmutableMessageLiteGenerator::GenerateKotlinOrNull( + io::Printer* printer) const { // Generate getFieldOrNull getters for all optional message fields. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); diff --git a/src/google/protobuf/compiler/java/name_resolver.cc b/src/google/protobuf/compiler/java/name_resolver.cc index e07f140097..ee5cf5c212 100644 --- a/src/google/protobuf/compiler/java/name_resolver.cc +++ b/src/google/protobuf/compiler/java/name_resolver.cc @@ -342,6 +342,21 @@ std::string ClassNameResolver::GetKotlinExtensionsClassName( descriptor->file(), true, true, true); } +std::string ClassNameResolver::GetKotlinExtensionsClassNameEscaped( + const Descriptor* descriptor) { + std::string name_without_package = ClassNameWithoutPackageKotlin(descriptor); + std::string full_name = GetClassFullName( + name_without_package, descriptor->file(), true, true, true); + std::string name_without_package_suffix = + absl::StrCat(".", name_without_package, "Kt"); + size_t package_end = full_name.rfind(name_without_package_suffix); + if (package_end != std::string::npos) { + return absl::StrCat("`", full_name.substr(0, package_end), "`", + name_without_package_suffix); + } + return full_name; +} + std::string ClassNameResolver::GetJavaMutableClassName( const Descriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false), diff --git a/src/google/protobuf/compiler/java/name_resolver.h b/src/google/protobuf/compiler/java/name_resolver.h index fe74a7d89f..b3b0b2eab8 100644 --- a/src/google/protobuf/compiler/java/name_resolver.h +++ b/src/google/protobuf/compiler/java/name_resolver.h @@ -102,6 +102,7 @@ class ClassNameResolver { std::string GetJavaImmutableClassName(const ServiceDescriptor* descriptor); std::string GetKotlinFactoryName(const Descriptor* descriptor); std::string GetKotlinExtensionsClassName(const Descriptor* descriptor); + std::string GetKotlinExtensionsClassNameEscaped(const Descriptor* descriptor); std::string GetJavaMutableClassName(const Descriptor* descriptor); std::string GetJavaMutableClassName(const EnumDescriptor* descriptor); std::string GetJavaMutableClassName(const ServiceDescriptor* descriptor);