THRIFT-121. Support arbitrary type annotations
Adds syntax for attaching arbitrary key/value pairs to types.
These annotations can be accessed by individual generators to alter
the code they produce.
This version supports annotations on container types and structures.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@724954 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h
index 09e386f..6f178bd 100644
--- a/compiler/cpp/src/parse/t_type.h
+++ b/compiler/cpp/src/parse/t_type.h
@@ -8,6 +8,7 @@
#define T_TYPE_H
#include <string>
+#include <map>
#include <cstring>
#include "t_doc.h"
@@ -114,6 +115,7 @@
return rv;
}
+ std::map<std::string, std::string> annotations_;
protected:
t_type() :
@@ -148,4 +150,14 @@
uint8_t fingerprint_[fingerprint_len];
};
+
+/**
+ * Placeholder struct for returning the key and value of an annotation
+ * during parsing.
+ */
+struct t_annotation {
+ std::string key;
+ std::string val;
+};
+
#endif
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy
index e5f1736..f27e9ab 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -56,6 +56,7 @@
t_field* tfield;
char* dtext;
t_field::e_req ereq;
+ t_annotation* tannot;
}
/**
@@ -142,6 +143,7 @@
%type<ttype> BaseType
%type<ttype> ContainerType
+%type<ttype> SimpleContainerType
%type<ttype> MapType
%type<ttype> SetType
%type<ttype> ListType
@@ -152,6 +154,10 @@
%type<ttypedef> Typedef
%type<ttype> DefinitionType
+%type<ttype> TypeAnnotations
+%type<ttype> TypeAnnotationList
+%type<tannot> TypeAnnotation
+
%type<tfield> Field
%type<iconst> FieldIdentifier
%type<ereq> FieldRequiredness
@@ -658,12 +664,16 @@
}
Struct:
- tok_struct tok_identifier XsdAll '{' FieldList '}'
+ tok_struct tok_identifier XsdAll '{' FieldList '}' TypeAnnotations
{
pdebug("Struct -> tok_struct tok_identifier { FieldList }");
- $5->set_name($2);
$5->set_xsd_all($3);
$$ = $5;
+ $$->set_name($2);
+ if ($7 != NULL) {
+ $$->annotations_ = $7->annotations_;
+ delete $7;
+ }
y_field_val = -1;
}
@@ -997,20 +1007,30 @@
$$ = g_type_double;
}
-ContainerType:
+ContainerType: SimpleContainerType TypeAnnotations
+ {
+ pdebug("ContainerType -> SimpleContainerType TypeAnnotations");
+ $$ = $1;
+ if ($2 != NULL) {
+ $$->annotations_ = $2->annotations_;
+ delete $2;
+ }
+ }
+
+SimpleContainerType:
MapType
{
- pdebug("ContainerType -> MapType");
+ pdebug("SimpleContainerType -> MapType");
$$ = $1;
}
| SetType
{
- pdebug("ContainerType -> SetType");
+ pdebug("SimpleContainerType -> SetType");
$$ = $1;
}
| ListType
{
- pdebug("ContainerType -> ListType");
+ pdebug("SimpleContainerType -> ListType");
$$ = $1;
}
@@ -1054,4 +1074,38 @@
$$ = NULL;
}
+TypeAnnotations:
+ '(' TypeAnnotationList ')'
+ {
+ pdebug("TypeAnnotations -> ( TypeAnnotationList )");
+ $$ = $2;
+ }
+|
+ {
+ $$ = NULL;
+ }
+
+TypeAnnotationList:
+ TypeAnnotationList TypeAnnotation
+ {
+ pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation");
+ $$ = $1;
+ $$->annotations_[$2->key] = $2->val;
+ delete $2;
+ }
+|
+ {
+ /* Just use a dummy structure to hold the annotations. */
+ $$ = new t_struct(g_program);
+ }
+
+TypeAnnotation:
+ tok_identifier '=' tok_literal CommaOrSemicolonOptional
+ {
+ pdebug("TypeAnnotation -> tok_identifier = tok_literal");
+ $$ = new t_annotation;
+ $$->key = $1;
+ $$->val = $3;
+ }
+
%%
diff --git a/test/AnnotationTest.thrift b/test/AnnotationTest.thrift
new file mode 100644
index 0000000..64e8d82
--- /dev/null
+++ b/test/AnnotationTest.thrift
@@ -0,0 +1,12 @@
+typedef list<i32> ( cpp.template = "std::list" ) int_linked_list
+
+struct foo {
+ 1: i32 bar;
+ 2: i32 baz;
+ 3: i32 qux;
+ 4: i32 bop;
+} (
+ cpp.type = "DenseFoo",
+ python.type = "DenseFoo",
+ java.final = "",
+)