Commit 55a16ee8 authored by Kenton Varda's avatar Kenton Varda

Merge pull request #84 from jjwchoy/name-annotations

Added 'name' annotation for the C++ annotation to override the basename ...
parents 63ccf60f fc176b80
......@@ -3,7 +3,7 @@ Those contributions are copyright the respective authors and licensed by them
under the same BSD license terms as the rest of the library.
Kenton Varda <temporal@gmail.com>: Primary Author
Jason Choy <jjwchoy@gmail.com>: kj/threadlocal.h and other iOS tweaks
Jason Choy <jjwchoy@gmail.com>: kj/threadlocal.h and other iOS tweaks, `name` annotation in C++ code generator
Remy Blank <rblank@google.com> (contributions copyright Google Inc.): KJ Timers
This file does not list people who maintain their own Cap'n Proto
......
......@@ -25,3 +25,4 @@
$namespace("capnp::annotations");
annotation namespace(file): Text;
annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
......@@ -8,19 +8,19 @@ namespace schemas {
static const ::capnp::_::AlignedData<19> b_b9c6f99ebf805f2c = {
{ 0, 0, 0, 0, 5, 0, 5, 0,
44, 95, 128, 191, 158, 249, 198, 185,
16, 0, 0, 0, 5, 0, 1, 0,
20, 0, 0, 0, 5, 0, 1, 0,
129, 78, 48, 184, 123, 125, 248, 189,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
17, 0, 0, 0, 210, 0, 0, 0,
17, 0, 0, 0, 242, 0, 0, 0,
29, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
24, 0, 0, 0, 2, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 97, 112, 110, 112, 47, 99, 43,
43, 46, 99, 97, 112, 110, 112, 58,
110, 97, 109, 101, 115, 112, 97, 99,
101, 0, 0, 0, 0, 0, 0, 0,
115, 114, 99, 47, 99, 97, 112, 110,
112, 47, 99, 43, 43, 46, 99, 97,
112, 110, 112, 58, 110, 97, 109, 101,
115, 112, 97, 99, 101, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0,
12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
......@@ -30,6 +30,31 @@ const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = {
0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 19, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr
};
static const ::capnp::_::AlignedData<19> b_f264a779fef191ce = {
{ 0, 0, 0, 0, 5, 0, 5, 0,
206, 145, 241, 254, 121, 167, 100, 242,
20, 0, 0, 0, 5, 0, 252, 7,
129, 78, 48, 184, 123, 125, 248, 189,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
17, 0, 0, 0, 202, 0, 0, 0,
29, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
24, 0, 0, 0, 2, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
115, 114, 99, 47, 99, 97, 112, 110,
112, 47, 99, 43, 43, 46, 99, 97,
112, 110, 112, 58, 110, 97, 109, 101,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0,
12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
const ::capnp::_::RawSchema s_f264a779fef191ce = {
0xf264a779fef191ce, b_f264a779fef191ce.words, 19, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr
};
} // namespace schemas
namespace _ { // private
} // namespace _ (private)
......
......@@ -23,6 +23,7 @@ namespace capnp {
namespace schemas {
extern const ::capnp::_::RawSchema s_b9c6f99ebf805f2c;
extern const ::capnp::_::RawSchema s_f264a779fef191ce;
} // namespace schemas
namespace _ { // private
......
......@@ -54,6 +54,7 @@ namespace capnp {
namespace {
static constexpr uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull;
static constexpr uint64_t NAME_ANNOTATION_ID = 0xf264a779fef191ceull;
static constexpr const char* FIELD_SIZE_NAMES[] = {
"VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE"
......@@ -190,14 +191,15 @@ private:
auto node = schema.getProto();
if (node.getScopeId() == 0) {
usedImports.insert(node.getId());
for (auto annotation: node.getAnnotations()) {
if (annotation.getId() == NAMESPACE_ANNOTATION_ID) {
return kj::strTree(" ::", annotation.getValue().getText());
}
KJ_IF_MAYBE(ns, annotationValue(node, NAMESPACE_ANNOTATION_ID)) {
return kj::strTree(" ::", ns->getText());
}
return kj::strTree(" ");
} else {
Schema parent = schemaLoader.get(node.getScopeId());
KJ_IF_MAYBE(annotatedName, annotationValue(node, NAME_ANNOTATION_ID)) {
return kj::strTree(cppFullName(parent), "::", annotatedName->getText());
}
for (auto nested: parent.getProto().getNestedNodes()) {
if (nested.getId() == node.getId()) {
return kj::strTree(cppFullName(parent), "::", nested.getName());
......@@ -270,6 +272,25 @@ private:
KJ_UNREACHABLE;
}
template <typename P>
kj::Maybe<schema::Value::Reader> annotationValue(P proto, uint64_t annotationId) {
for (auto annotation: proto.getAnnotations()) {
if (annotation.getId() == annotationId) {
return annotation.getValue();
}
}
return nullptr;
}
template <typename P>
kj::StringPtr protoName(P proto) {
KJ_IF_MAYBE(name, annotationValue(proto, NAME_ANNOTATION_ID)) {
return name->getText();
} else {
return proto.getName();
}
}
kj::StringTree literalValue(schema::Type::Reader type, schema::Value::Reader value) {
switch (value.which()) {
case schema::Value::VOID: return kj::strTree(" ::capnp::VOID");
......@@ -289,7 +310,7 @@ private:
if (value.getEnum() < schema.getEnumerants().size()) {
return kj::strTree(
cppFullName(schema), "::",
toUpperCase(schema.getEnumerants()[value.getEnum()].getProto().getName()));
toUpperCase(protoName(schema.getEnumerants()[value.getEnum()].getProto())));
} else {
return kj::strTree("static_cast<", cppFullName(schema), ">(", value.getEnum(), ")");
}
......@@ -571,11 +592,12 @@ private:
FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field field) {
auto proto = field.getProto();
kj::String titleCase = toTitleCase(proto.getName());
auto baseName = protoName(proto);
kj::String titleCase = toTitleCase(baseName);
DiscriminantChecks unionDiscrim;
if (hasDiscriminantValue(proto)) {
unionDiscrim = makeDiscriminantChecks(scope, proto.getName(), field.getContainingStruct());
unionDiscrim = makeDiscriminantChecks(scope, baseName, field.getContainingStruct());
}
switch (proto.which()) {
......@@ -1153,6 +1175,9 @@ private:
StructText makeStructText(kj::StringPtr scope, kj::StringPtr name, StructSchema schema,
kj::Array<kj::StringTree> nestedTypeDecls) {
auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name);
auto subScope = kj::str(fullName, "::");
auto fieldTexts = KJ_MAP(f, schema.getFields()) { return makeFieldText(subScope, f); };
......@@ -1175,7 +1200,7 @@ private:
" enum Which: uint16_t {\n",
KJ_MAP(f, structNode.getFields()) {
if (hasDiscriminantValue(f)) {
return kj::strTree(" ", toUpperCase(f.getName()), ",\n");
return kj::strTree(" ", toUpperCase(protoName(f)), ",\n");
} else {
return kj::strTree();
}
......@@ -1218,7 +1243,7 @@ private:
MethodText makeMethodText(kj::StringPtr interfaceName, InterfaceSchema::Method method) {
auto proto = method.getProto();
auto name = proto.getName();
auto name = protoName(proto);
auto titleCase = toTitleCase(name);
auto paramSchema = schemaLoader.get(proto.getParamStructType()).asStruct();
auto resultSchema = schemaLoader.get(proto.getResultStructType()).asStruct();
......@@ -1539,6 +1564,9 @@ private:
NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope,
kj::StringPtr name, Schema schema) {
auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name);
auto subScope = kj::str(fullName, "::");
auto hexId = kj::hex(proto.getId());
......@@ -1554,7 +1582,7 @@ private:
for (auto field: proto.getStruct().getFields()) {
if (field.isGroup()) {
nestedTexts.add(makeNodeText(
namespace_, subScope, toTitleCase(field.getName()),
namespace_, subScope, toTitleCase(protoName(field)),
schemaLoader.get(field.getGroup().getTypeId())));
}
}
......@@ -1565,7 +1593,7 @@ private:
auto paramsProto = schemaLoader.get(method.getParamStructType()).getProto();
if (paramsProto.getScopeId() == 0) {
nestedTexts.add(makeNodeText(namespace_, subScope,
toTitleCase(kj::str(method.getName(), "Params")), params));
toTitleCase(kj::str(protoName(method), "Params")), params));
}
}
{
......@@ -1573,7 +1601,7 @@ private:
auto resultsProto = schemaLoader.get(method.getResultStructType()).getProto();
if (resultsProto.getScopeId() == 0) {
nestedTexts.add(makeNodeText(namespace_, subScope,
toTitleCase(kj::str(method.getName(), "Results")), results));
toTitleCase(kj::str(protoName(method), "Results")), results));
}
}
}
......@@ -1694,6 +1722,9 @@ private:
kj::StringPtr name, Schema schema,
kj::Array<kj::StringTree> nestedTypeDecls) {
auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name);
auto hexId = kj::hex(proto.getId());
......@@ -1734,7 +1765,7 @@ private:
scope.size() == 0 ? kj::strTree() : kj::strTree(
" enum class ", name, ": uint16_t {\n",
KJ_MAP(e, enumerants) {
return kj::strTree(" ", toUpperCase(e.getProto().getName()), ",\n");
return kj::strTree(" ", toUpperCase(protoName(e.getProto())), ",\n");
},
" };\n"
"\n"),
......@@ -1742,7 +1773,7 @@ private:
scope.size() > 0 ? kj::strTree() : kj::strTree(
"enum class ", name, ": uint16_t {\n",
KJ_MAP(e, enumerants) {
return kj::strTree(" ", toUpperCase(e.getProto().getName()), ",\n");
return kj::strTree(" ", toUpperCase(protoName(e.getProto())), ",\n");
},
"};\n"
"\n"),
......
......@@ -1651,6 +1651,47 @@ TEST(Encoding, HasEmptyStructList) {
EXPECT_EQ(2, root.totalSize().wordCount);
}
TEST(Encoding, NameAnnotation) {
EXPECT_EQ(2, static_cast<uint16_t>(test::RenamedStruct::RenamedEnum::QUX));
EXPECT_EQ(2, static_cast<uint16_t>(test::RenamedStruct::RenamedNestedStruct::RenamedDeeplyNestedEnum::GARPLY));
MallocMessageBuilder message;
auto root = message.initRoot<test::RenamedStruct>();
root.setGoodFieldName(true);
EXPECT_EQ(true, root.getGoodFieldName());
EXPECT_TRUE(root.isGoodFieldName());
root.setBar(0xff);
EXPECT_FALSE(root.isGoodFieldName());
root.setAnotherGoodFieldName(test::RenamedStruct::RenamedEnum::QUX);
EXPECT_EQ(test::RenamedStruct::RenamedEnum::QUX, root.getAnotherGoodFieldName());
EXPECT_FALSE(root.getRenamedUnion().isQux());
auto quxBuilder = root.getRenamedUnion().initQux();
EXPECT_TRUE(root.getRenamedUnion().isQux());
EXPECT_FALSE(root.getRenamedUnion().getQux().hasAnotherGoodNestedFieldName());
quxBuilder.setGoodNestedFieldName(true);
EXPECT_EQ(true, quxBuilder.getGoodNestedFieldName());
EXPECT_FALSE(quxBuilder.hasAnotherGoodNestedFieldName());
auto nestedFieldBuilder = quxBuilder.initAnotherGoodNestedFieldName();
EXPECT_TRUE(quxBuilder.hasAnotherGoodNestedFieldName());
nestedFieldBuilder.setGoodNestedFieldName(true);
EXPECT_EQ(true, nestedFieldBuilder.getGoodNestedFieldName());
EXPECT_FALSE(nestedFieldBuilder.hasAnotherGoodNestedFieldName());
EXPECT_FALSE(root.getRenamedUnion().isRenamedGroup());
auto renamedGroupBuilder = root.getRenamedUnion().initRenamedGroup();
EXPECT_TRUE(root.getRenamedUnion().isRenamedGroup());
test::RenamedInterface::RenamedMethodParams::Reader renamedInterfaceParams;
renamedInterfaceParams.getRenamedParam();
}
} // namespace
} // namespace _ (private)
} // namespace capnp
......@@ -688,3 +688,41 @@ struct TestProvisionId {}
struct TestRecipientId {}
struct TestThirdPartyCapId {}
struct TestJoinResult {}
struct TestNameAnnotation $Cxx.name("RenamedStruct") {
union {
badFieldName @0 :Bool $Cxx.name("goodFieldName");
bar @1 :Int8;
}
enum BadlyNamedEnum $Cxx.name("RenamedEnum") {
foo @0;
bar @1;
baz @2 $Cxx.name("qux");
}
anotherBadFieldName @2 :BadlyNamedEnum $Cxx.name("anotherGoodFieldName");
struct NestedStruct $Cxx.name("RenamedNestedStruct") {
badNestedFieldName @0 :Bool $Cxx.name("goodNestedFieldName");
anotherBadNestedFieldName @1 :NestedStruct $Cxx.name("anotherGoodNestedFieldName");
enum DeeplyNestedEnum $Cxx.name("RenamedDeeplyNestedEnum") {
quux @0;
corge @1;
grault @2 $Cxx.name("garply");
}
}
badlyNamedUnion :union $Cxx.name("renamedUnion") {
badlyNamedGroup :group $Cxx.name("renamedGroup") {
foo @3 :Void;
bar @4 :Void;
}
baz @5 :NestedStruct $Cxx.name("qux");
}
}
interface TestNameAnnotationInterface $Cxx.name("RenamedInterface") {
badlyNamedMethod @0 (badlyNamedParam :UInt8 $Cxx.name("renamedParam")) $Cxx.name("renamedMethod");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment