Skip to content

Commit

Permalink
[Proto] Keep track of the names of Services, Messages, and Enums
Browse files Browse the repository at this point in the history
In order to construct a fully qualified Java import from the proto file,
we need to know the values of the "java_package" option as well as the
services, messages, and enums in the proto file. The "java_pacakge"
option is already recorded. In this commit, we add support for parsing
the names of the services, message, and enums of a proto file and
tracking them in the FileInfo struct.
  • Loading branch information
ckilian867 committed Jul 26, 2024
1 parent 5385064 commit 4818ff2
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
50 changes: 49 additions & 1 deletion language/proto/fileinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ type FileInfo struct {
Imports []string

HasServices bool

Services []string
Messages []string
Enums []string
}

// Option represents a top-level option statement in a .proto file. Only
Expand Down Expand Up @@ -77,6 +81,36 @@ func protoFileInfo(dir, name string) FileInfo {
case match[serviceSubexpIndex] != nil:
info.HasServices = true

// match is of the format "service ServiceName {".
// extract just the service name
fullMatch := string(match[serviceSubexpIndex])
serviceName, ok := extractObjectName(fullMatch)

if ok {
info.Services = append(info.Services, serviceName)
}

case match[messageSubexpIndex] != nil:
// match is of the format "message MessageName {".
// extract just the message name
fullMatch := string(match[messageSubexpIndex])
messageName, ok := extractObjectName(fullMatch)

if ok {
info.Messages = append(info.Messages, messageName)
}

case match[enumSubexpIndex] != nil:
// match is of the format "enum EnumName {".
// extract just the enum name
fullMatch := string(match[enumSubexpIndex])
enumName, ok := extractObjectName(fullMatch)

if ok {
info.Enums = append(info.Enums, enumName)
}


default:
// Comment matched. Nothing to extract.
}
Expand All @@ -92,6 +126,8 @@ const (
optkeySubexpIndex = 3
optvalSubexpIndex = 4
serviceSubexpIndex = 5
messageSubexpIndex = 6
enumSubexpIndex = 7
)

// Based on https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
Expand All @@ -107,8 +143,10 @@ func buildProtoRegexp() *regexp.Regexp {
packageStmt := `\bpackage\s*(?P<package>` + fullIdent + `)\s*;`
optionStmt := `\boption\s*(?P<optkey>` + fullIdent + `)\s*=\s*(?P<optval>` + strLit + `)\s*;`
serviceStmt := `(?P<service>service\s+` + ident + `\s*{)`
messageStmt := `(?P<message>message\s+` + ident + `\s*{)`
enumStmt := `(?P<enum>enum\s+` + ident + `\s*{)`
comment := `//[^\n]*`
protoReSrc := strings.Join([]string{importStmt, packageStmt, optionStmt, serviceStmt, comment}, "|")
protoReSrc := strings.Join([]string{importStmt, packageStmt, optionStmt, serviceStmt, messageStmt, enumStmt, comment}, "|")
return regexp.MustCompile(protoReSrc)
}

Expand Down Expand Up @@ -136,3 +174,13 @@ func unquoteProtoString(q []byte) string {
}
return s
}

func extractObjectName(fullMatch string) (response string, ok bool) {
fields := strings.Fields(fullMatch)
if len(fields) < 2 {
// expect as least two fields. Input is malformed
return "", false
}

return strings.TrimSuffix(fields[1], "{"), true
}
82 changes: 82 additions & 0 deletions language/proto/fileinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ func TestProtoRegexpGroupNames(t *testing.T) {
"optkey": optkeySubexpIndex,
"optval": optvalSubexpIndex,
"service": serviceSubexpIndex,
"message": messageSubexpIndex,
"enum": enumSubexpIndex,
}
for name, index := range nameMap {
if names[index] != name {
Expand Down Expand Up @@ -109,6 +111,7 @@ import "second.proto";`,
proto: `service ChatService {}`,
want: FileInfo{
HasServices: true,
Services: []string{"ChatService"},
},
},
{
Expand All @@ -117,6 +120,7 @@ import "second.proto";`,
proto: `service ChatService {}`,
want: FileInfo{
HasServices: true,
Services: []string{"ChatService"},
},
},
{
Expand All @@ -125,6 +129,7 @@ import "second.proto";`,
proto: `service ChatService{}`,
want: FileInfo{
HasServices: true,
Services: []string{"ChatService"},
},
},
{
Expand All @@ -141,6 +146,80 @@ import "second.proto";`,
proto: `message serviceAccount { string service = 1; }`,
want: FileInfo{
HasServices: false,
Messages: []string{"serviceAccount"},
},
},{
desc: "multiple service names",
name: "service.proto",
proto: `service ServiceA { string service = 1; }
service ServiceB { string service = 1; }
service ServiceC{ string service = 1; }
serviceServiceD { string service = 1; }
service message { string service = 1; }
service enum { string service = 1; }
`,
want: FileInfo{
HasServices: true,
Services: []string{"ServiceA", "ServiceB", "ServiceC", "message", "enum"},
},
},{
desc: "multiple message names",
name: "messages.proto",
proto: `message MessageA { string message = 1; }
message MessageB { string message = 1; }
message MessageC{ string message = 1; }
messageMessageD { string message = 1; }
message service { string service = 1; }
message enum { string service = 1; }
`,
want: FileInfo{
Messages: []string{"MessageA", "MessageB", "MessageC", "service", "enum"},
},
},{
desc: "multiple enum names",
name: "enums.proto",
proto: `enum EnumA {
ENUM_VALUE_A = 1;
ENUM_VALUE_B = 2;
}
enum EnumB {
ENUM_VALUE_C = 1;
ENUM_VALUE_D = 2;
}
enum EnumC{
ENUM_VALUE_E = 1;
ENUM_VALUE_F = 2;
}
enumEnumD {
ENUM_VALUE_G = 1;
ENUM_VALUE_H = 2;
}
enum service {
ENUM_VALUE_I = 1;
ENUM_VALUE_J = 2;
}
enum message {
ENUM_VALUE_K = 1;
ENUM_VALUE_L = 2;
}
`,
want: FileInfo{
Enums: []string{"EnumA", "EnumB", "EnumC", "service", "message"},
},
},
} {
Expand All @@ -162,6 +241,9 @@ import "second.proto";`,
Imports: got.Imports,
Options: got.Options,
HasServices: got.HasServices,
Services: got.Services,
Messages: got.Messages,
Enums: got.Enums,
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("got %#v; want %#v", got, tc.want)
Expand Down
3 changes: 3 additions & 0 deletions language/proto/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func TestGeneratePackage(t *testing.T) {
"protos/sub/sub.proto",
},
HasServices: true,
Services: []string{"Quux"},
},
},
Imports: map[string]bool{
Expand Down Expand Up @@ -235,6 +236,7 @@ func TestFileModeImports(t *testing.T) {
Path: filepath.Join(dir, "foo.proto"),
Name: "foo.proto",
PackageName: "file_mode",
Messages: []string{"Foo"},
},
},
Imports: map[string]bool{},
Expand All @@ -252,6 +254,7 @@ func TestFileModeImports(t *testing.T) {
Imports: []string{
"file_mode/foo.proto",
},
Messages: []string{"Bar"},
},
},
// Imports should contain foo.proto. This is specific to file mode.
Expand Down

0 comments on commit 4818ff2

Please sign in to comment.