Since multiple people are expressing interest in pushing this along I thought it best to write down what we want v2 to be. This will ensure everyone is on the same page and allow parallel work to be done. This is meant to be a living document that will be edited as things change.
Summary:
- Simplify use in a toolchain.
- Leverage parsing & pruning to generate things other than Wire-specific Java code.
- Alter the behavior of the Wire-specific generated Java code.
- More advanced CLI
- Other features
Simplify use in a toolchain.
The Wire compiler has no API which means you are forced to interact with by calling the main()
method with CLI arguments.
For example,
task generateProtos << {
def protoRoots = project.file("proto_roots.txt").readLines()
def protoFiles = project.file("proto_files.txt").readLines()
def compiler = new WireCompiler(protoDir.toString(), protoFiles, protoRoots, 'src/main/java', null, false)
compiler.compile()
}
This is unsatisfactory. The tests for wire are also forced into doing this.
We should provide an API which lets you very easily specify all of the required data for compilation.
Random example that's not a suggestion of what the actual API should be:
new WireCompiler()
.addDirectory(new File("/foo/bar/protos"))
.addProtoRoot("example.thing.Foo")
.addProtoRoot("example.thing.Bar")
.build();
(This is done on version-two branch)
Leverage parsing & pruning to generate things other than Wire-specific Java code.
Code to serialize protocol buffers are not the only thing you want to generate. We want to generate Retrofit interfaces based on RPC definitions, for example. Additionally there's no reason that you couldn't general Python, Objective-C, or even protobuf-compliant code.
The parsing of protos is easy but pruning them requires contextual knowledge of where they are stored and dependency resolution semantics is hard. Since Wire is already doing all of this work, we should expose it for others to consume and do with what they'd like.
After parsing and pruning an immutable representation of everything required for generating code should be available. We can re-use protoparser's model objects since they are immutable and simple omit the messages, enums, and rpcs which have been pruned.
(This is done on version-two branch)
Alter the behavior of the Wire-specific generated Java code.
This is similar to the previous point, but involves hooking into the Wire-specific code generation rather than a completely separate generator.
For example, naming of fields and methods is a high-contention point that could easily be solved by a method which can be overridden to specify a different naming scheme.
protected String toJavaName(String protoName) {
// Note: You would want to cache the converter, obviously.
return CaseFormat.LOWER_UNDERSCORE.converterTo(CaseFormat.LOWER_CAMEL).convert(protoName);
}
This would also allow for hooks to augment generation. The JavaWriter
could be handed to empty protected
methods before and after certain blocks of code for additional logic to be put in place. For example, additional validation code in the constructor which takes the builder.
See Shawn's branch for a specific spike on what might be needed. Maybe we can get him to write a more fleshed out design here.
More advanced CLI
With all of the aforementioned changes, it should come as no surprise that a more powerful CLI is needed. By not attempting to mirror the protoc
CLI we are unblocked to make something that's both simple, declarative, and powerful.
more to come...
Other features
- Protos are not always on-disk and we should not require them to be. In a traditional Maven build they are often placed in src/main/protos and can be published in the artifact to Maven central or any other repository manager. We should support a way of loading them.
- Support multiple proto directories for dependency resolution.
TODO