Skip to content

Commit de674fc

Browse files
Merge pull request #208 from twirphp/fix-message-name
Fix nested message name generation
2 parents e50220f + bfe00e4 commit de674fc

2 files changed

Lines changed: 29 additions & 25 deletions

File tree

protoc-gen-twirp_php/internal/php/func.go

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
package php
22

33
import (
4+
"slices"
45
"strings"
56

67
"google.golang.org/protobuf/compiler/protogen"
78
"google.golang.org/protobuf/reflect/protoreflect"
89
"google.golang.org/protobuf/types/descriptorpb"
910
)
1011

12+
// Code in this file is based on the original protoc compiler code for PHP:
13+
// https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/compiler/php/names.cc
14+
1115
// Reserved PHP keywords that must be prefixed with something.
16+
//
17+
// Source: https://github.com/protocolbuffers/protobuf/blob/6e393fd79667597aac2bb42511fb30c31ff1611d/src/google/protobuf/compiler/php/names.cc
1218
var reservedNames = []string{
1319
"abstract", "and", "array", "as", "break",
1420
"callable", "case", "catch", "class", "clone",
1521
"const", "continue", "declare", "default", "die",
1622
"do", "echo", "else", "elseif", "empty",
1723
"enddeclare", "endfor", "endforeach", "endif", "endswitch",
1824
"endwhile", "eval", "exit", "extends", "final",
19-
"for", "foreach", "function", "global", "goto",
20-
"if", "implements", "include", "include_once", "instanceof",
21-
"insteadof", "interface", "isset", "list", "namespace",
22-
"new", "or", "print", "private", "protected",
23-
"public", "require", "require_once", "return", "static",
24-
"switch", "throw", "trait", "try", "unset",
25-
"use", "var", "while", "xor", "int",
26-
"float", "bool", "string", "true", "false",
27-
"null", "void", "iterable",
25+
"finally", "fn", "for", "foreach", "function",
26+
"global", "goto", "if", "implements", "include",
27+
"include_once", "instanceof", "insteadof", "interface", "isset",
28+
"list", "match", "namespace", "new", "or",
29+
"parent", "print", "private", "protected", "public",
30+
"readonly", "require", "require_once", "return", "self",
31+
"static", "switch", "throw", "trait", "try",
32+
"unset", "use", "var", "while", "xor",
33+
"yield", "int", "float", "bool", "string",
34+
"true", "false", "null", "void", "iterable",
2835
}
2936

3037
// ClassNamePrefix calculates class name prefix.
@@ -43,16 +50,7 @@ func classNamePrefix(className string, file protoreflect.FileDescriptor) string
4350
}
4451

4552
// Check if the class name matches a reserved name
46-
isReserved := false
47-
for _, name := range reservedNames {
48-
if name == strings.ToLower(className) {
49-
isReserved = true
50-
51-
break
52-
}
53-
}
54-
55-
if isReserved {
53+
if slices.Contains(reservedNames, strings.ToLower(className)) {
5654
// Google internal classes receive a different prefix
5755
if file.Package() == "google.protobuf" {
5856
return "GPB"
@@ -85,12 +83,12 @@ func namespace(file protoreflect.FileDescriptor) string {
8583

8684
// Path guesses the path of the file based on the (internally calculated) namespace.
8785
func Path(file *protogen.File) string {
88-
return strings.Replace(Namespace(file), "\\", "/", -1)
86+
return strings.ReplaceAll(Namespace(file), "\\", "/")
8987
}
9088

9189
// PathFromNamespace guesses the path of the file based on the namespace.
9290
func PathFromNamespace(ns string) string {
93-
return strings.Replace(ns, "\\", "/", -1)
91+
return strings.ReplaceAll(ns, "\\", "/")
9492
}
9593

9694
// Name generates a name from a proto reference.
@@ -129,9 +127,14 @@ func ServiceName(file *protogen.File, svc *protogen.Service) string {
129127
}
130128

131129
// MessageName transforms a message name into a PHP compatible one.
132-
func MessageName(file *protogen.File, message *protogen.Message) string {
133-
className := string(message.Desc.Name())
134-
parentFile := message.Desc.ParentFile()
130+
func MessageName(_ *protogen.File, message *protogen.Message) string {
131+
desc := message.Desc
132+
parentFile := desc.ParentFile()
133+
className := classNamePrefix(string(desc.Name()), parentFile) + string(desc.Name())
134+
135+
for parent, ok := desc.Parent().(protoreflect.MessageDescriptor); ok && parent != nil; parent, ok = parent.Parent().(protoreflect.MessageDescriptor) {
136+
className = classNamePrefix(string(parent.Name()), parentFile) + string(parent.Name()) + "\\" + className
137+
}
135138

136-
return "\\" + namespacedName(classNamePrefix(className, parentFile)+className, parentFile)
139+
return "\\" + namespacedName(className, parentFile)
137140
}

tests/namespace/test.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ final public static function exit(): void
4242
Assert::classExists(\Twirp\Tests\Namespace\Proto\HaberdasherAbstractClient::class);
4343
Assert::classExists(\Twirp\Tests\Namespace\Proto\HaberdasherJsonClient::class);
4444
Assert::interfaceExists(\Twirp\Tests\Namespace\Proto\Haberdasher::class);
45+
Assert::exit();

0 commit comments

Comments
 (0)