Skip to content

Commit c1aae38

Browse files
thedavekwonfacebook-github-bot
authored andcommitted
Implement Annotation population in TypeSystemFacade
Summary: This should be specific to annotation since annotaiton and defaults are stored differently in schema.thrift Reviewed By: praihan Differential Revision: D79923159 fbshipit-source-id: ede4e983f6b88af4631037463e11970d46cc8388
1 parent a86f830 commit c1aae38

File tree

2 files changed

+128
-10
lines changed

2 files changed

+128
-10
lines changed

third-party/thrift/src/thrift/lib/cpp2/schema/SyntaxGraph.cpp

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,106 @@ void SyntaxGraph::printTo(
699699
}
700700

701701
namespace {
702+
703+
type_system::SerializableRecord toTypeSystemAnnotation(
704+
const TypeRef& annotationType, const folly::dynamic& data);
705+
706+
type_system::SerializableRecord toTypeSystemAnnotation(
707+
const StructuredNode& node, const folly::dynamic& data) {
708+
type_system::SerializableRecord::FieldSet result;
709+
for (const auto& [fieldName, fieldData] : data.items()) {
710+
const FieldNode& field = node.at(fieldName.asString());
711+
result.emplace(field.id(), toTypeSystemAnnotation(field.type(), fieldData));
712+
}
713+
return type_system::SerializableRecord(std::move(result));
714+
}
715+
716+
type_system::SerializableRecord toTypeSystemAnnotation(
717+
const TypeRef& annotationType, const folly::dynamic& data) {
718+
return annotationType.visit(
719+
[&](const StructuredNode& node) {
720+
return toTypeSystemAnnotation(node, data);
721+
},
722+
[&](const EnumNode&) {
723+
auto result = type_system::SerializableRecord::Int32(
724+
static_cast<int32_t>(data.asInt()));
725+
return type_system::SerializableRecord{std::move(result)};
726+
},
727+
[&](const TypedefNode& node) {
728+
return toTypeSystemAnnotation(node.targetType(), data);
729+
},
730+
[&](const List& node) {
731+
type_system::SerializableRecord::List l;
732+
l.reserve(data.size());
733+
for (const auto& element : data) {
734+
l.push_back(toTypeSystemAnnotation(node.elementType(), element));
735+
}
736+
return type_system::SerializableRecord{std::move(l)};
737+
},
738+
[&](const Set& node) {
739+
type_system::SerializableRecord::Set s;
740+
s.reserve(data.size());
741+
for (const auto& element : data) {
742+
s.insert(toTypeSystemAnnotation(node.elementType(), element));
743+
}
744+
return type_system::SerializableRecord{std::move(s)};
745+
},
746+
[&](const Map& node) {
747+
type_system::SerializableRecord::Map m;
748+
m.reserve(data.size());
749+
for (const auto& [key, value] : data.items()) {
750+
m.emplace(
751+
toTypeSystemAnnotation(node.keyType(), key),
752+
toTypeSystemAnnotation(node.valueType(), value));
753+
}
754+
return type_system::SerializableRecord{std::move(m)};
755+
},
756+
[&](const Primitive& node) -> type_system::SerializableRecord {
757+
switch (node) {
758+
case Primitive::BOOL:
759+
return {type_system::SerializableRecord::Bool(data.asBool())};
760+
case Primitive::BYTE:
761+
return {type_system::SerializableRecord::Int8(
762+
static_cast<int8_t>(data.asInt()))};
763+
case Primitive::I16:
764+
return {type_system::SerializableRecord::Int16(
765+
static_cast<int16_t>(data.asInt()))};
766+
case Primitive::I32:
767+
return {type_system::SerializableRecord::Int32(
768+
static_cast<int32_t>(data.asInt()))};
769+
case Primitive::I64:
770+
return {type_system::SerializableRecord::Int64(
771+
static_cast<int8_t>(data.asInt()))};
772+
case Primitive::DOUBLE:
773+
return {type_system::SerializableRecord::Float32(
774+
static_cast<float>(data.asDouble()))};
775+
case Primitive::FLOAT:
776+
return {type_system::SerializableRecord::Float64(data.asDouble())};
777+
break;
778+
case Primitive::STRING:
779+
return {type_system::SerializableRecord::Text(data.asString())};
780+
case Primitive::BINARY:
781+
return {type_system::SerializableRecord::ByteArray(
782+
folly::IOBuf::fromString(
783+
std::make_unique<std::string>(data.asString())))};
784+
}
785+
folly::assume_unreachable();
786+
});
787+
}
788+
789+
type_system::AnnotationsMap toTypeSystemAnnotations(
790+
folly::span<const Annotation> annotations) {
791+
type_system::AnnotationsMap annotationsMap;
792+
annotationsMap.reserve(annotations.size());
793+
// TODO(dokwon): only preserve annotations with @thrift.RuntimeAnnotation
794+
for (const Annotation& annotation : annotations) {
795+
annotationsMap.emplace(
796+
annotation.type().asStruct().uri(),
797+
toTypeSystemAnnotation(annotation.type(), annotation.value()));
798+
}
799+
return annotationsMap;
800+
}
801+
702802
class TypeSystemFacade final : public type_system::TypeSystem {
703803
// Thrift files (and therefore SyntaxGraph) cannot define opaque alias types.
704804
// Therefore, they are not necessary for the TypeSystem for SyntaxGraph.
@@ -845,17 +945,17 @@ class TypeSystemFacade final : public type_system::TypeSystem {
845945
std::vector<type_system::EnumNode::Value> values;
846946
values.reserve(e.values().size());
847947
for (const auto& value : e.values()) {
848-
// TODO: annotations
849948
values.emplace_back(type_system::EnumNode::Value{
850949
std::string(value.name()),
851950
value.i32(),
852-
type_system::AnnotationsMap{}});
951+
toTypeSystemAnnotations(value.annotations())});
853952
}
854-
// TODO: annotations
855953
auto [entry, _] = cache_.emplace(
856954
sgDef,
857955
type_system::EnumNode{
858-
type_system::Uri(e.uri()), std::move(values), {}});
956+
type_system::Uri(e.uri()),
957+
std::move(values),
958+
toTypeSystemAnnotations(e.definition().annotations())});
859959
reverseCache_.emplace(
860960
&std::get<type_system::EnumNode>(entry->second), sgDef);
861961
},
@@ -891,10 +991,7 @@ class TypeSystemFacade final : public type_system::TypeSystem {
891991
convertType(field.type()),
892992
// TODO: default value
893993
std::nullopt,
894-
// TODO: annotations
895-
type_system::AnnotationsMap{}
896-
897-
);
994+
toTypeSystemAnnotations(field.annotations()));
898995
}
899996
return fields;
900997
};
@@ -904,14 +1001,14 @@ class TypeSystemFacade final : public type_system::TypeSystem {
9041001
type_system::Uri(s.uri()),
9051002
makeFields(s),
9061003
false,
907-
type_system::AnnotationsMap{}};
1004+
toTypeSystemAnnotations(s.definition().annotations())};
9081005
},
9091006
[&](const UnionNode& s) {
9101007
std::get<type_system::UnionNode>(tsDef) = type_system::UnionNode{
9111008
type_system::Uri(s.uri()),
9121009
makeFields(s),
9131010
false,
914-
type_system::AnnotationsMap{}};
1011+
toTypeSystemAnnotations(s.definition().annotations())};
9151012
},
9161013
[](const auto& n) {
9171014
folly::throw_exception<std::logic_error>(fmt::format(

third-party/thrift/src/thrift/lib/cpp2/schema/test/SyntaxGraphTest.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ TEST_F(ServiceSchemaTest, asTypeSystem) {
775775
type_system::PresenceQualifier::OPTIONAL_);
776776
EXPECT_EQ(structNode.fields()[0].type().asStruct().uri(), uri);
777777
EXPECT_EQ(&structNode.fields()[0].type().asStruct(), &structNode);
778+
778779
EXPECT_EQ(&syntaxGraph.asTypeSystemStructNode(def->asStruct()), &structNode);
779780
const auto& sgStructNode = syntaxGraph.asSyntaxGraphStructNode(structNode);
780781
EXPECT_EQ(&sgStructNode, &def->asStruct());
@@ -794,14 +795,34 @@ TEST_F(ServiceSchemaTest, asTypeSystem) {
794795
&mainProgram.definitionsByName().at("TestUnion")->asUnion(),
795796
&sgUnionNode);
796797
checkAnnotationsOnTestUnion(sgUnionNode);
798+
const auto& annot = *unionNode.getAnnotationOrNull(
799+
"meta.com/thrift_test/TestStructuredAnnotation");
800+
EXPECT_EQ(annot.asFieldSet().at(FieldId{1}).asInt64(), 3);
801+
EXPECT_EQ(
802+
annot.asFieldSet().at(FieldId{2}).asFieldSet().at(FieldId{1}).asInt64(),
803+
4);
797804

798805
uri = "meta.com/thrift_test/TestEnum";
799806
const type_system::EnumNode& enumNode =
800807
typeSystem.getUserDefinedTypeOrThrow(uri).asEnum();
801808
EXPECT_EQ(enumNode.uri(), uri);
809+
EXPECT_EQ(
810+
enumNode
811+
.getAnnotationOrNull("meta.com/thrift_test/TestStructuredAnnotation")
812+
->asFieldSet()
813+
.at(FieldId{1})
814+
.asInt64(),
815+
3);
802816
EXPECT_EQ(enumNode.values().size(), 3);
803817
EXPECT_EQ(enumNode.values()[0].name, "UNSET");
804818
EXPECT_EQ(enumNode.values()[0].i32, 0);
819+
EXPECT_EQ(
820+
enumNode.values()[0]
821+
.getAnnotationOrNull("meta.com/thrift_test/TestStructuredAnnotation")
822+
->asFieldSet()
823+
.at(FieldId{1})
824+
.asInt64(),
825+
4);
805826
EXPECT_EQ(enumNode.values()[1].name, "VALUE_1");
806827
EXPECT_EQ(enumNode.values()[1].i32, 1);
807828
EXPECT_EQ(enumNode.values()[2].name, "VALUE_2");

0 commit comments

Comments
 (0)