@@ -73,6 +73,50 @@ namespace {
7373constexpr absl::string_view kAnyMessageName = " Any" ;
7474constexpr absl::string_view kAnyProtoFile = " google/protobuf/any.proto" ;
7575
76+ const absl::flat_hash_set<absl::string_view>& FileScopeKnownNames () {
77+ static constexpr const char * kValue [] = {
78+ " swap" ,
79+ };
80+ static const auto * const methods = new absl::flat_hash_set<absl::string_view>(
81+ std::begin (kValue ), std::end (kValue ));
82+ return *methods;
83+ }
84+
85+ const absl::flat_hash_set<absl::string_view>& MessageKnownMethodsCamelCase () {
86+ static constexpr const char * kMessageKnownMethods [] = {
87+ " GetDescriptor" , " GetReflection" , " default_instance" ,
88+ " Swap" , " UnsafeArenaSwap" , " New" ,
89+ " CopyFrom" , " MergeFrom" , " IsInitialized" ,
90+ " GetMetadata" , " Clear" ,
91+ };
92+ static const auto * const methods = new absl::flat_hash_set<absl::string_view>(
93+ std::begin (kMessageKnownMethods ), std::end (kMessageKnownMethods ));
94+ return *methods;
95+ }
96+
97+ const absl::flat_hash_set<absl::string_view>&
98+ MessageKnownNullaryMethodsSnakeCase () {
99+ static constexpr const char * kMessageKnownMethods [] = {
100+ " unknown_fields" ,
101+ " mutable_unknown_fields" ,
102+ " descriptor" ,
103+ " default_instance" ,
104+ };
105+ static const auto * const methods = new absl::flat_hash_set<absl::string_view>(
106+ std::begin (kMessageKnownMethods ), std::end (kMessageKnownMethods ));
107+ return *methods;
108+ }
109+
110+ const absl::flat_hash_set<absl::string_view>&
111+ MessageKnownNonNullaryMethodsSnakeCase () {
112+ static constexpr const char * kMessageKnownMethods [] = {
113+ " swap" ,
114+ };
115+ static const auto * const methods = new absl::flat_hash_set<absl::string_view>(
116+ std::begin (kMessageKnownMethods ), std::end (kMessageKnownMethods ));
117+ return *methods;
118+ }
119+
76120static const char * const kKeywordList [] = {
77121 // clang-format off
78122 " NULL" ,
@@ -406,12 +450,14 @@ std::string ClassName(const Descriptor* descriptor) {
406450 if (parent) absl::StrAppend (&res, ClassName (parent), " _" );
407451 absl::StrAppend (&res, descriptor->name ());
408452 if (IsMapEntryMessage (descriptor)) absl::StrAppend (&res, " _DoNotUse" );
409- return ResolveKeyword (res);
453+ // This is the mangled message name which always goes in file scope.
454+ return ResolveKnownNameCollisions (res, NameContext::kFile , NameKind::kType );
410455}
411456
412457std::string ClassName (const EnumDescriptor* enum_descriptor) {
413458 if (enum_descriptor->containing_type () == nullptr ) {
414- return ResolveKeyword (enum_descriptor->name ());
459+ return ResolveKnownNameCollisions (enum_descriptor->name (),
460+ NameContext::kFile , NameKind::kType );
415461 } else {
416462 return absl::StrCat (ClassName (enum_descriptor->containing_type ()), " _" ,
417463 enum_descriptor->name ());
@@ -436,9 +482,14 @@ std::string QualifiedClassName(const EnumDescriptor* d) {
436482}
437483
438484std::string ExtensionName (const FieldDescriptor* d) {
439- if (const Descriptor* scope = d->extension_scope ())
440- return absl::StrCat (ClassName (scope), " ::" , ResolveKeyword (d->name ()));
441- return ResolveKeyword (d->name ());
485+ if (const Descriptor* scope = d->extension_scope ()) {
486+ return absl::StrCat (
487+ ClassName (scope), " ::" ,
488+ ResolveKnownNameCollisions (d->name (), NameContext::kMessage ,
489+ NameKind::kValue ));
490+ }
491+ return ResolveKnownNameCollisions (d->name (), NameContext::kFile ,
492+ NameKind::kValue );
442493}
443494
444495std::string QualifiedExtensionName (const FieldDescriptor* d,
@@ -452,23 +503,53 @@ std::string QualifiedExtensionName(const FieldDescriptor* d) {
452503}
453504
454505std::string ResolveKeyword (absl::string_view name) {
455- if (Keywords ().count (name) > 0 ) {
506+ if (Keywords ().contains (name)) {
456507 return absl::StrCat (name, " _" );
457508 }
458509 return std::string (name);
459510}
460511
461- std::string DotsToColons (absl::string_view name) {
462- std::vector<std::string> scope = absl::StrSplit (name, ' .' , absl::SkipEmpty ());
463- for (auto & word : scope) {
464- word = ResolveKeyword (word);
512+ std::string ResolveKnownNameCollisions (absl::string_view name,
513+ NameContext name_context,
514+ NameKind name_kind) {
515+ const auto has_conflict = [&] {
516+ if (Keywords ().contains (name)) return true ;
517+
518+ switch (name_kind) {
519+ // We assume the style guide: types are CamelCase, fields are snake_case.
520+ case NameKind::kType :
521+ // Types can't overload names of existing functions.
522+ return MessageKnownMethodsCamelCase ().contains (name);
523+ case NameKind::kValue :
524+ if (name_context == NameContext::kFile ) {
525+ // At file scope we don't have the normal names, except a few.
526+ return FileScopeKnownNames ().contains (name);
527+ }
528+ // Values can't overload names of existing functions.
529+ return MessageKnownNullaryMethodsSnakeCase ().contains (name) ||
530+ MessageKnownNonNullaryMethodsSnakeCase ().contains (name);
531+ case NameKind::kFunction :
532+ // For functions, we can't overload existing nullary functions.
533+ // Non-nullary functions are fine.
534+ return MessageKnownNullaryMethodsSnakeCase ().contains (name);
535+ }
536+ return false ;
537+ };
538+ if (has_conflict ()) {
539+ return absl::StrCat (name, " _" );
465540 }
466- return absl::StrJoin (scope, " :: " );
541+ return std::string (name );
467542}
468543
469544std::string Namespace (absl::string_view package) {
470545 if (package.empty ()) return " " ;
471- return absl::StrCat (" ::" , DotsToColons (package));
546+
547+ std::vector<std::string> scope =
548+ absl::StrSplit (package, ' .' , absl::SkipEmpty ());
549+ for (auto & word : scope) {
550+ word = ResolveKeyword (word);
551+ }
552+ return absl::StrCat (" ::" , absl::StrJoin (scope, " ::" ));
472553}
473554
474555std::string Namespace (const FileDescriptor* d) { return Namespace (d, {}); }
@@ -555,12 +636,17 @@ std::string SuperClassName(const Descriptor* descriptor,
555636}
556637
557638std::string FieldName (const FieldDescriptor* field) {
639+ if (field->containing_type () != nullptr &&
640+ field->containing_type ()->options ().no_standard_descriptor_accessor () &&
641+ field->name () == " descriptor" ) {
642+ // Special case for `optional no_standard_descriptor_accessor = true;`
643+ return " descriptor" ;
644+ }
558645 std::string result = std::string (field->name ());
559646 absl::AsciiStrToLower (&result);
560- if (Keywords ().count (result) > 0 ) {
561- result.append (" _" );
562- }
563- return result;
647+ ABSL_CHECK (field->containing_type () != nullptr );
648+ return ResolveKnownNameCollisions (result, NameContext::kMessage ,
649+ NameKind::kFunction );
564650}
565651
566652std::string FieldMemberName (const FieldDescriptor* field, bool split) {
@@ -589,11 +675,7 @@ std::string QualifiedOneofCaseConstantName(const FieldDescriptor* field) {
589675}
590676
591677std::string EnumValueName (const EnumValueDescriptor* enum_value) {
592- std::string result = std::string (enum_value->name ());
593- if (Keywords ().count (result) > 0 ) {
594- result.append (" _" );
595- }
596- return result;
678+ return ResolveKeyword (enum_value->name ());
597679}
598680
599681int EstimateAlignmentSize (const FieldDescriptor* field) {
0 commit comments