Skip to content

Commit 72d8f07

Browse files
authored
Merge pull request #85 from salesforce/bugfix/jprotoc-nested
Correctly handle nested types
2 parents 394cfdd + a70de97 commit 72d8f07

File tree

5 files changed

+106
-24
lines changed

5 files changed

+106
-24
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
syntax = "proto3";
2+
3+
package nested;
4+
5+
message Outer { // Level 0
6+
enum FooEnum {
7+
FOO = 0;
8+
BAR = 1;
9+
CHEESE = 2;
10+
}
11+
message MiddleAA { // Level 1
12+
13+
message Inner { // Level 2
14+
int64 ival = 1;
15+
bool booly = 2;
16+
Outer.FooEnum enum = 3;
17+
}
18+
}
19+
message MiddleBB { // Level 1
20+
message Inner { // Level 2
21+
int32 ival = 1;
22+
bool booly = 2;
23+
Outer.FooEnum enum = 3;
24+
}
25+
}
26+
}
27+
28+
service Nested {
29+
rpc doNested (Outer.MiddleAA.Inner) returns (Outer.MiddleBB.Inner) {}
30+
}

jprotoc/src/main/java/com/salesforce/jprotoc/Generator.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.io.InputStream;
1919
import java.io.InputStreamReader;
2020
import java.io.StringWriter;
21+
import java.util.Collections;
22+
import java.util.List;
2123
import java.util.stream.Stream;
2224

2325
/**
@@ -28,10 +30,25 @@ public abstract class Generator {
2830

2931
/**
3032
* Processes a generator request into a set of files to output.
33+
*
34+
* @deprecated use {@link #generateFiles(PluginProtos.CodeGeneratorRequest)} and return a List instead of a Stream.
3135
* @param request The raw generator request from protoc.
3236
* @return The completed files to write out.
3337
*/
34-
public abstract Stream<PluginProtos.CodeGeneratorResponse.File> generate(PluginProtos.CodeGeneratorRequest request) throws GeneratorException;
38+
@Deprecated()
39+
public Stream<PluginProtos.CodeGeneratorResponse.File> generate(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
40+
return Stream.empty();
41+
}
42+
43+
/**
44+
* Processes a generator request into a set of files to output.
45+
*
46+
* @param request The raw generator request from protoc.
47+
* @return The completed files to write out.
48+
*/
49+
public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
50+
return Collections.emptyList();
51+
}
3552

3653
/**
3754
* Executes a mustache template against a generatorContext object to generate an output string.

jprotoc/src/main/java/com/salesforce/jprotoc/ProtoTypeMap.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,45 @@ public static ProtoTypeMap of(@Nonnull Collection<DescriptorProtos.FileDescripto
5757
getJavaOuterClassname(fileDescriptor, fileOptions);
5858

5959

60-
60+
// Identify top-level enums
6161
fileDescriptor.getEnumTypeList().forEach(
6262
e -> types.put(
6363
protoPackage + "." + e.getName(),
6464
toJavaTypeName(e.getName(), enclosingClassName, javaPackage)));
6565

66+
// Identify top-level messages, and nested types
6667
fileDescriptor.getMessageTypeList().forEach(
67-
m -> types.put(
68-
protoPackage + "." + m.getName(),
69-
toJavaTypeName(m.getName(), enclosingClassName, javaPackage)));
68+
m -> recursivelyAddTypes(types, m, protoPackage, enclosingClassName, javaPackage)
69+
);
7070
}
7171

7272
return new ProtoTypeMap(types.build());
7373
}
7474

75+
private static void recursivelyAddTypes(ImmutableMap.Builder<String, String> types, DescriptorProtos.DescriptorProto m, String protoPackage, String enclosingClassName, String javaPackage) {
76+
// Identify current type
77+
types.put(
78+
protoPackage + "." + m.getName(),
79+
toJavaTypeName(m.getName(), enclosingClassName, javaPackage));
80+
81+
// Identify any nested Enums
82+
m.getEnumTypeList().forEach(
83+
e -> types.put(
84+
protoPackage + "." + e.getName(),
85+
toJavaTypeName(e.getName(),
86+
enclosingClassName,
87+
javaPackage)));
88+
89+
// Recursively identify any nested types
90+
m.getNestedTypeList().forEach(
91+
n -> recursivelyAddTypes(
92+
types,
93+
n,
94+
protoPackage + "." + m.getName(),
95+
enclosingClassName + "." + m.getName(),
96+
javaPackage));
97+
}
98+
7599
/**
76100
* Returns the full Java type name for the given proto type.
77101
*

jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.Collections;
1717
import java.util.List;
1818
import java.util.stream.Collectors;
19+
import java.util.stream.Stream;
1920
import javax.annotation.Nonnull;
2021

2122
/**
@@ -71,15 +72,18 @@ public static void generate(
7172
generatorRequestBytes, extensionRegistry);
7273

7374
// Run each file generator, collecting the output
74-
List<PluginProtos.CodeGeneratorResponse.File> outputFiles = generators
75+
Stream<PluginProtos.CodeGeneratorResponse.File> oldWay = generators
7576
.stream()
76-
.flatMap(gen -> gen.generate(request))
77-
.collect(Collectors.toList());
77+
.flatMap(gen -> gen.generate(request));
78+
79+
Stream<PluginProtos.CodeGeneratorResponse.File> newWay = generators
80+
.stream()
81+
.flatMap(gen -> gen.generateFiles(request).stream());
7882

7983
// Send the files back to protoc
8084
PluginProtos.CodeGeneratorResponse response = PluginProtos.CodeGeneratorResponse
8185
.newBuilder()
82-
.addAllFile(outputFiles)
86+
.addAllFile(Stream.concat(oldWay, newWay).collect(Collectors.toList()))
8387
.build();
8488
response.writeTo(System.out);
8589

jprotoc/src/main/java/com/salesforce/jprotoc/jdk8/Jdk8Generator.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import java.util.ArrayList;
1919
import java.util.List;
20-
import java.util.stream.Stream;
2120

2221
/**
2322
* Generates a set of gRPC stubs that support JDK8 {@link java.util.concurrent.CompletableFuture}.
@@ -30,24 +29,32 @@ public static void main(String[] args) {
3029
private static final String CLASS_SUFFIX = "Grpc8";
3130

3231
@Override
33-
public Stream<PluginProtos.CodeGeneratorResponse.File> generate(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
32+
public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
3433
final ProtoTypeMap protoTypeMap = ProtoTypeMap.of(request.getProtoFileList());
34+
List<PluginProtos.CodeGeneratorResponse.File> files = new ArrayList<>();
3535

36-
return request.getProtoFileList().stream()
37-
.filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName()))
38-
.flatMap(f -> extractContext(protoTypeMap, f))
39-
.map(this::buildFile);
36+
for (DescriptorProtos.FileDescriptorProto protoFile : request.getProtoFileList()) {
37+
if (request.getFileToGenerateList().contains(protoFile.getName())) {
38+
for (Context ctx : extractContext(protoTypeMap, protoFile)) {
39+
files.add(buildFile(ctx));
40+
}
41+
}
42+
}
43+
44+
return files;
4045
}
4146

42-
private Stream<Context> extractContext(ProtoTypeMap protoTypeMap, DescriptorProtos.FileDescriptorProto proto) {
43-
return proto.getServiceList().stream()
44-
.map(s -> extractServiceContext(protoTypeMap, s))
45-
.map(ctx -> {
46-
ctx.packageName = extractPackageName(proto); return ctx;
47-
})
48-
.map(ctx -> {
49-
ctx.protoName = proto.getName(); return ctx;
50-
});
47+
private List<Context> extractContext(ProtoTypeMap protoTypeMap, DescriptorProtos.FileDescriptorProto proto) {
48+
List<Context> contexts = new ArrayList<>();
49+
50+
for (DescriptorProtos.ServiceDescriptorProto service : proto.getServiceList()) {
51+
Context ctx = extractServiceContext(protoTypeMap, service);
52+
ctx.packageName = extractPackageName(proto);
53+
ctx.protoName = proto.getName();
54+
contexts.add(ctx);
55+
}
56+
57+
return contexts;
5158
}
5259

5360
private String extractPackageName(DescriptorProtos.FileDescriptorProto proto) {

0 commit comments

Comments
 (0)