generic interface generation (WIP

This commit is contained in:
Vaci Koblizek 2020-10-26 10:07:34 +00:00
parent 86ccdd5a55
commit 2d8fe31a59
2 changed files with 124 additions and 74 deletions

View file

@ -381,6 +381,7 @@ private:
return kj::strTree("org.capnproto.ListList.", suffix, "<", kj::mv(inner), ">");
}
case schema::Type::INTERFACE:
return kj::strTree("org.capnproto.PrimitiveList.Void.", suffix);
case schema::Type::ANY_POINTER:
KJ_FAIL_REQUIRE("unimplemented");
}
@ -811,6 +812,23 @@ private:
return kj::str(typeName(type, kj::str("factory")));
}
}
case schema::Type::INTERFACE: {
auto interfaceSchema = type.asInterface();
auto node = interfaceSchema.getProto();
if (node.getIsGeneric()) {
auto factoryArgs = getFactoryArguments(interfaceSchema, interfaceSchema);
return kj::strTree(
javaFullName(interfaceSchema), ".newFactory(",
kj::StringTree(
KJ_MAP(arg, factoryArgs) {
return kj::strTree(arg);
}, ","),
")"
).flatten();
} else {
return kj::str(typeName(type, kj::str("factory")));
}
}
default:
KJ_UNREACHABLE;
}
@ -1031,7 +1049,7 @@ private:
} else if (kind == FieldKind::INTERFACE) {
auto factoryArg = kj::str(typeName(field.getType()), ".factory");
auto factoryArg = makeFactoryArg(field.getType());
auto clientType = kj::str(typeName(field.getType()), ".Client");
return FieldText {
@ -1627,10 +1645,88 @@ private:
auto typeName = javaFullName(schema);
kj::String genericParamTypes;
if (proto.getIsGeneric()) {
auto typeParams = getTypeParameters(schema);
genericParamTypes = kj::strTree(
"<",
kj::StringTree(
KJ_MAP(arg, typeParams) {
return kj::strTree(arg);
}, ", "),
">").flatten();
}
else {
genericParamTypes = kj::str("");
}
auto typeParamVec = getTypeParameters(schema);
bool hasTypeParams = typeParamVec.size() > 0;
kj::StringTree readerTypeParamsTree;
kj::StringTree builderTypeParamsTree;
kj::StringTree factoryTypeParamsTree;
if (hasTypeParams) {
builderTypeParamsTree = kj::strTree(
"<",
kj::StringTree(KJ_MAP(p, typeParamVec) {
return kj::strTree(p, "_Builder");
}, ", "),
">");
readerTypeParamsTree = kj::strTree(
"<",
kj::StringTree(KJ_MAP(p, typeParamVec) {
return kj::strTree(p, "_Reader");
}, ", "),
">");
factoryTypeParamsTree = kj::strTree(
"<",
kj::StringTree(KJ_MAP(p, typeParamVec) {
return kj::strTree(p, "_Builder, ", p, "_Reader");
}, ", "),
">");
}
kj::String readerTypeParams = readerTypeParamsTree.flatten();
auto readerTypeParamsInferred = (hasTypeParams ? "<>" : "");
kj::String builderTypeParams = builderTypeParamsTree.flatten();
kj::String factoryTypeParams = factoryTypeParamsTree.flatten();
kj::StringTree factoryArgs = kj::StringTree(KJ_MAP(p, typeParamVec) {
return kj::strTree("org.capnproto.PointerFactory<", p, "_Builder, ", p, "_Reader> ", p, "_Factory");
}, ", ");
kj::StringTree factoryMembers = kj::strTree(KJ_MAP(p, typeParamVec) {
return kj::strTree(spaces(indent), " final org.capnproto.PointerFactory<", p, "_Builder, ", p, "_Reader> ", p, "_Factory;\n");
});
kj::String factoryRef = hasTypeParams
? kj::str(kj::strTree("newFactory(",
kj::StringTree(KJ_MAP(p, typeParamVec) {
return kj::strTree(p, "_Factory");
}, ", ")
, ")"))
: kj::str("factory");
return InterfaceText {
kj::strTree(
spaces(indent), "public static class ", name, " {\n",
spaces(indent), " public static final class Factory extends org.capnproto.Capability.Factory<Client> {\n",
spaces(indent), "public static class ", name, genericParamTypes, " {\n",
spaces(indent), " public static final class Factory", factoryTypeParams, "\n",
spaces(indent), " extends org.capnproto.Capability.Factory<Client> {\n",
factoryMembers.flatten(),
spaces(indent), " public Factory(",
factoryArgs.flatten(),
") {\n",
KJ_MAP(p, typeParamVec) {
return kj::strTree(spaces(indent), " this.", p, "_Factory = ", p, "_Factory;\n");
},
spaces(indent), " }\n",
//spaces(indent), " public static final class Factory extends org.capnproto.Capability.Factory<Client> {\n",
spaces(indent), " public final Client newClient(org.capnproto.ClientHook hook) {\n",
spaces(indent), " return new Client(hook);\n",
spaces(indent), " }\n",
@ -1712,8 +1808,7 @@ private:
paramType = kj::str(titleCase, "Params");
genericParamType = kj::str(paramType);
} else {
KJ_FAIL_REQUIRE("Generic interfaces not supported");
//genericParamType = paramType;
genericParamType = kj::str(paramType);
//genericParamType.addMemberTemplate(kj::str(titleCase, "Params"), nullptr);
//paramType.addMemberTemplate(kj::str(titleCase, "Params"),
// kj::heapArray(implicitParams.asPtr()));
@ -1734,8 +1829,7 @@ private:
resultType = kj::str(titleCase, "Results");
genericResultType = kj::str(resultType);
} else {
KJ_FAIL_REQUIRE("Generic interfaces not supported");
//genericResultType = resultType;
genericResultType = kj::str(resultType);
//genericResultType.addMemberTemplate(kj::str(titleCase, "Results"), nullptr);
//resultType.addMemberTemplate(kj::str(titleCase, "Results"),
// kj::heapArray(implicitParams.asPtr()));
@ -1761,6 +1855,28 @@ private:
kj::String paramFactory = kj::str(shortParamType, ".factory");
kj::String resultFactory = kj::str(shortResultType, ".factory");
if (paramProto.getIsGeneric()) {
auto paramFactoryArgs = getFactoryArguments(paramSchema, paramSchema);
paramFactory = paramFactoryArgs.size() == 0
? kj::str(shortParamType, ".factory")
: kj::strTree("newFactory(",
kj::StringTree(KJ_MAP(arg, paramFactoryArgs) {
return kj::strTree(arg);
}, ", "),
")").flatten();
}
if (resultProto.getIsGeneric()) {
auto resultFactoryArgs = getFactoryArguments(resultSchema, paramSchema);
resultFactory = resultFactoryArgs.size() == 0
? kj::str(shortResultType, ".factory")
: kj::strTree("newFactory(",
kj::StringTree(KJ_MAP(arg, resultFactoryArgs) {
return kj::strTree(arg);
}, ", "),
")").flatten();
}
auto interfaceProto = method.getContainingInterface().getProto();
uint64_t interfaceId = interfaceProto.getId();
auto interfaceIdHex = kj::hex(interfaceId);

View file

@ -1,66 +0,0 @@
package org.capnproto;
import org.capnproto.demo.Demo;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class LocalCapabilityTest {
@Test
public void testLocalServer() throws ExecutionException, InterruptedException {
var demo = new TestCap0Impl();
var client = new Demo.TestCap0.Client(demo);
var request = client.testMethod0Request();
var params = request.getParams();
params.setParam0(4321);
var response = request.send();
var results = response.get();
Assert.assertEquals(params.getParam0(), results.getResult0());
}
@Test
public void testGenericServer() throws ExecutionException, InterruptedException {
var demo = new TestCap0Impl();
var client = new Demo.TestCap0.Client(demo);
var request = client.testMethod0Request();
var params = request.getParams();
var response = request.send();
var results = response.get();
Assert.assertEquals(params.getParam0(), results.getResult0());
}
@Test
public void testLocalTwoStagePipeline() {
var server0 = new Demo.Iface0.Server() {
boolean method0called = false;
@Override
protected CompletableFuture<java.lang.Void> method0(CallContext<Demo.Iface0.Method0Params.Reader, Demo.Iface0.Method0Results.Builder> ctx) {
method0called = true;
return CompletableFuture.completedFuture(null);
}
};
var server1 = new Demo.Iface1.Server() {
@Override
protected CompletableFuture<java.lang.Void> method1(CallContext<Demo.Iface1.Method1Params.Reader, Demo.Iface1.Method1Results.Builder> ctx) {
ctx.getResults().setResult0(new Demo.Iface0.Client(server0));
return CompletableFuture.completedFuture(null);
}
};
var iface1Client = new Demo.Iface1.Client(server1);
var request1 = iface1Client.method1Request();
var response = request1.send();
var iface0 = response.getResult0();
var request0 = iface0.method0Request();
var response0 = request0.send();
response0.join();
Assert.assertTrue(!response0.isCompletedExceptionally());
Assert.assertTrue(server0.method0called);
}
}