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 ...@@ -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. under the same BSD license terms as the rest of the library.
Kenton Varda <temporal@gmail.com>: Primary Author 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 Remy Blank <rblank@google.com> (contributions copyright Google Inc.): KJ Timers
This file does not list people who maintain their own Cap'n Proto This file does not list people who maintain their own Cap'n Proto
......
...@@ -25,3 +25,4 @@ ...@@ -25,3 +25,4 @@
$namespace("capnp::annotations"); $namespace("capnp::annotations");
annotation namespace(file): Text; annotation namespace(file): Text;
annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
...@@ -8,19 +8,19 @@ namespace schemas { ...@@ -8,19 +8,19 @@ namespace schemas {
static const ::capnp::_::AlignedData<19> b_b9c6f99ebf805f2c = { static const ::capnp::_::AlignedData<19> b_b9c6f99ebf805f2c = {
{ 0, 0, 0, 0, 5, 0, 5, 0, { 0, 0, 0, 0, 5, 0, 5, 0,
44, 95, 128, 191, 158, 249, 198, 185, 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, 129, 78, 48, 184, 123, 125, 248, 189,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 29, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24, 0, 0, 0, 2, 0, 1, 0, 24, 0, 0, 0, 2, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99, 97, 112, 110, 112, 47, 99, 43, 115, 114, 99, 47, 99, 97, 112, 110,
43, 46, 99, 97, 112, 110, 112, 58, 112, 47, 99, 43, 43, 46, 99, 97,
110, 97, 109, 101, 115, 112, 97, 99, 112, 110, 112, 58, 110, 97, 109, 101,
101, 0, 0, 0, 0, 0, 0, 0, 115, 112, 97, 99, 101, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
12, 0, 0, 0, 0, 0, 0, 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,
...@@ -30,6 +30,31 @@ const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = { ...@@ -30,6 +30,31 @@ const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = {
0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 19, nullptr, nullptr, 0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 19, nullptr, nullptr,
0, 0, nullptr, 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 schemas
namespace _ { // private namespace _ { // private
} // namespace _ (private) } // namespace _ (private)
......
...@@ -23,6 +23,7 @@ namespace capnp { ...@@ -23,6 +23,7 @@ namespace capnp {
namespace schemas { namespace schemas {
extern const ::capnp::_::RawSchema s_b9c6f99ebf805f2c; extern const ::capnp::_::RawSchema s_b9c6f99ebf805f2c;
extern const ::capnp::_::RawSchema s_f264a779fef191ce;
} // namespace schemas } // namespace schemas
namespace _ { // private namespace _ { // private
......
...@@ -54,6 +54,7 @@ namespace capnp { ...@@ -54,6 +54,7 @@ namespace capnp {
namespace { namespace {
static constexpr uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull; static constexpr uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull;
static constexpr uint64_t NAME_ANNOTATION_ID = 0xf264a779fef191ceull;
static constexpr const char* FIELD_SIZE_NAMES[] = { static constexpr const char* FIELD_SIZE_NAMES[] = {
"VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE" "VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE"
...@@ -190,14 +191,15 @@ private: ...@@ -190,14 +191,15 @@ private:
auto node = schema.getProto(); auto node = schema.getProto();
if (node.getScopeId() == 0) { if (node.getScopeId() == 0) {
usedImports.insert(node.getId()); usedImports.insert(node.getId());
for (auto annotation: node.getAnnotations()) { KJ_IF_MAYBE(ns, annotationValue(node, NAMESPACE_ANNOTATION_ID)) {
if (annotation.getId() == NAMESPACE_ANNOTATION_ID) { return kj::strTree(" ::", ns->getText());
return kj::strTree(" ::", annotation.getValue().getText());
}
} }
return kj::strTree(" "); return kj::strTree(" ");
} else { } else {
Schema parent = schemaLoader.get(node.getScopeId()); 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()) { for (auto nested: parent.getProto().getNestedNodes()) {
if (nested.getId() == node.getId()) { if (nested.getId() == node.getId()) {
return kj::strTree(cppFullName(parent), "::", nested.getName()); return kj::strTree(cppFullName(parent), "::", nested.getName());
...@@ -270,6 +272,25 @@ private: ...@@ -270,6 +272,25 @@ private:
KJ_UNREACHABLE; 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) { kj::StringTree literalValue(schema::Type::Reader type, schema::Value::Reader value) {
switch (value.which()) { switch (value.which()) {
case schema::Value::VOID: return kj::strTree(" ::capnp::VOID"); case schema::Value::VOID: return kj::strTree(" ::capnp::VOID");
...@@ -289,7 +310,7 @@ private: ...@@ -289,7 +310,7 @@ private:
if (value.getEnum() < schema.getEnumerants().size()) { if (value.getEnum() < schema.getEnumerants().size()) {
return kj::strTree( return kj::strTree(
cppFullName(schema), "::", cppFullName(schema), "::",
toUpperCase(schema.getEnumerants()[value.getEnum()].getProto().getName())); toUpperCase(protoName(schema.getEnumerants()[value.getEnum()].getProto())));
} else { } else {
return kj::strTree("static_cast<", cppFullName(schema), ">(", value.getEnum(), ")"); return kj::strTree("static_cast<", cppFullName(schema), ">(", value.getEnum(), ")");
} }
...@@ -571,11 +592,12 @@ private: ...@@ -571,11 +592,12 @@ private:
FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field field) { FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field field) {
auto proto = field.getProto(); auto proto = field.getProto();
kj::String titleCase = toTitleCase(proto.getName()); auto baseName = protoName(proto);
kj::String titleCase = toTitleCase(baseName);
DiscriminantChecks unionDiscrim; DiscriminantChecks unionDiscrim;
if (hasDiscriminantValue(proto)) { if (hasDiscriminantValue(proto)) {
unionDiscrim = makeDiscriminantChecks(scope, proto.getName(), field.getContainingStruct()); unionDiscrim = makeDiscriminantChecks(scope, baseName, field.getContainingStruct());
} }
switch (proto.which()) { switch (proto.which()) {
...@@ -1153,6 +1175,9 @@ private: ...@@ -1153,6 +1175,9 @@ private:
StructText makeStructText(kj::StringPtr scope, kj::StringPtr name, StructSchema schema, StructText makeStructText(kj::StringPtr scope, kj::StringPtr name, StructSchema schema,
kj::Array<kj::StringTree> nestedTypeDecls) { kj::Array<kj::StringTree> nestedTypeDecls) {
auto proto = schema.getProto(); auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name); auto fullName = kj::str(scope, name);
auto subScope = kj::str(fullName, "::"); auto subScope = kj::str(fullName, "::");
auto fieldTexts = KJ_MAP(f, schema.getFields()) { return makeFieldText(subScope, f); }; auto fieldTexts = KJ_MAP(f, schema.getFields()) { return makeFieldText(subScope, f); };
...@@ -1175,7 +1200,7 @@ private: ...@@ -1175,7 +1200,7 @@ private:
" enum Which: uint16_t {\n", " enum Which: uint16_t {\n",
KJ_MAP(f, structNode.getFields()) { KJ_MAP(f, structNode.getFields()) {
if (hasDiscriminantValue(f)) { if (hasDiscriminantValue(f)) {
return kj::strTree(" ", toUpperCase(f.getName()), ",\n"); return kj::strTree(" ", toUpperCase(protoName(f)), ",\n");
} else { } else {
return kj::strTree(); return kj::strTree();
} }
...@@ -1218,7 +1243,7 @@ private: ...@@ -1218,7 +1243,7 @@ private:
MethodText makeMethodText(kj::StringPtr interfaceName, InterfaceSchema::Method method) { MethodText makeMethodText(kj::StringPtr interfaceName, InterfaceSchema::Method method) {
auto proto = method.getProto(); auto proto = method.getProto();
auto name = proto.getName(); auto name = protoName(proto);
auto titleCase = toTitleCase(name); auto titleCase = toTitleCase(name);
auto paramSchema = schemaLoader.get(proto.getParamStructType()).asStruct(); auto paramSchema = schemaLoader.get(proto.getParamStructType()).asStruct();
auto resultSchema = schemaLoader.get(proto.getResultStructType()).asStruct(); auto resultSchema = schemaLoader.get(proto.getResultStructType()).asStruct();
...@@ -1539,6 +1564,9 @@ private: ...@@ -1539,6 +1564,9 @@ private:
NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope, NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope,
kj::StringPtr name, Schema schema) { kj::StringPtr name, Schema schema) {
auto proto = schema.getProto(); auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name); auto fullName = kj::str(scope, name);
auto subScope = kj::str(fullName, "::"); auto subScope = kj::str(fullName, "::");
auto hexId = kj::hex(proto.getId()); auto hexId = kj::hex(proto.getId());
...@@ -1554,7 +1582,7 @@ private: ...@@ -1554,7 +1582,7 @@ private:
for (auto field: proto.getStruct().getFields()) { for (auto field: proto.getStruct().getFields()) {
if (field.isGroup()) { if (field.isGroup()) {
nestedTexts.add(makeNodeText( nestedTexts.add(makeNodeText(
namespace_, subScope, toTitleCase(field.getName()), namespace_, subScope, toTitleCase(protoName(field)),
schemaLoader.get(field.getGroup().getTypeId()))); schemaLoader.get(field.getGroup().getTypeId())));
} }
} }
...@@ -1565,7 +1593,7 @@ private: ...@@ -1565,7 +1593,7 @@ private:
auto paramsProto = schemaLoader.get(method.getParamStructType()).getProto(); auto paramsProto = schemaLoader.get(method.getParamStructType()).getProto();
if (paramsProto.getScopeId() == 0) { if (paramsProto.getScopeId() == 0) {
nestedTexts.add(makeNodeText(namespace_, subScope, nestedTexts.add(makeNodeText(namespace_, subScope,
toTitleCase(kj::str(method.getName(), "Params")), params)); toTitleCase(kj::str(protoName(method), "Params")), params));
} }
} }
{ {
...@@ -1573,7 +1601,7 @@ private: ...@@ -1573,7 +1601,7 @@ private:
auto resultsProto = schemaLoader.get(method.getResultStructType()).getProto(); auto resultsProto = schemaLoader.get(method.getResultStructType()).getProto();
if (resultsProto.getScopeId() == 0) { if (resultsProto.getScopeId() == 0) {
nestedTexts.add(makeNodeText(namespace_, subScope, nestedTexts.add(makeNodeText(namespace_, subScope,
toTitleCase(kj::str(method.getName(), "Results")), results)); toTitleCase(kj::str(protoName(method), "Results")), results));
} }
} }
} }
...@@ -1694,6 +1722,9 @@ private: ...@@ -1694,6 +1722,9 @@ private:
kj::StringPtr name, Schema schema, kj::StringPtr name, Schema schema,
kj::Array<kj::StringTree> nestedTypeDecls) { kj::Array<kj::StringTree> nestedTypeDecls) {
auto proto = schema.getProto(); auto proto = schema.getProto();
KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) {
name = annotatedName->getText();
}
auto fullName = kj::str(scope, name); auto fullName = kj::str(scope, name);
auto hexId = kj::hex(proto.getId()); auto hexId = kj::hex(proto.getId());
...@@ -1734,7 +1765,7 @@ private: ...@@ -1734,7 +1765,7 @@ private:
scope.size() == 0 ? kj::strTree() : kj::strTree( scope.size() == 0 ? kj::strTree() : kj::strTree(
" enum class ", name, ": uint16_t {\n", " enum class ", name, ": uint16_t {\n",
KJ_MAP(e, enumerants) { KJ_MAP(e, enumerants) {
return kj::strTree(" ", toUpperCase(e.getProto().getName()), ",\n"); return kj::strTree(" ", toUpperCase(protoName(e.getProto())), ",\n");
}, },
" };\n" " };\n"
"\n"), "\n"),
...@@ -1742,7 +1773,7 @@ private: ...@@ -1742,7 +1773,7 @@ private:
scope.size() > 0 ? kj::strTree() : kj::strTree( scope.size() > 0 ? kj::strTree() : kj::strTree(
"enum class ", name, ": uint16_t {\n", "enum class ", name, ": uint16_t {\n",
KJ_MAP(e, enumerants) { KJ_MAP(e, enumerants) {
return kj::strTree(" ", toUpperCase(e.getProto().getName()), ",\n"); return kj::strTree(" ", toUpperCase(protoName(e.getProto())), ",\n");
}, },
"};\n" "};\n"
"\n"), "\n"),
......
...@@ -1651,6 +1651,47 @@ TEST(Encoding, HasEmptyStructList) { ...@@ -1651,6 +1651,47 @@ TEST(Encoding, HasEmptyStructList) {
EXPECT_EQ(2, root.totalSize().wordCount); 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
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
...@@ -688,3 +688,41 @@ struct TestProvisionId {} ...@@ -688,3 +688,41 @@ struct TestProvisionId {}
struct TestRecipientId {} struct TestRecipientId {}
struct TestThirdPartyCapId {} struct TestThirdPartyCapId {}
struct TestJoinResult {} 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