Interface methods can now be annotated.
The syntax is a strict subset of what Java supports. The following are valid
annotations:
@Fragile
@LotsOfStuff(single="yes", many={"a", "b", "c"})
An annotation either has no parameters (in which case the name is NOT followed
by parentheses) or is does and what follows the name is a parenthesized list
of name=value pairs, where each value is either a single quoted string literal
or a list of quoted string literals surrounded by curly braces.
Change-Id: I3c51d771b7d55c8d16531286d011f61be700a21c
diff --git a/AST.h b/AST.h
index 2f76f3d..0a1eea6 100644
--- a/AST.h
+++ b/AST.h
@@ -5,6 +5,8 @@
#include <android-base/macros.h>
#include <set>
#include <string>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
#include <utils/Vector.h>
#include "FQName.h"
diff --git a/Android.mk b/Android.mk
index 7ebd2f3..724ce81 100644
--- a/Android.mk
+++ b/Android.mk
@@ -6,6 +6,7 @@
LOCAL_IS_HOST_MODULE := true
LOCAL_SRC_FILES := \
+ Annotation.cpp \
ArrayType.cpp \
CompoundType.cpp \
Constant.cpp \
diff --git a/Annotation.cpp b/Annotation.cpp
new file mode 100644
index 0000000..d5692cf
--- /dev/null
+++ b/Annotation.cpp
@@ -0,0 +1,61 @@
+#include "Annotation.h"
+
+#include "Formatter.h"
+
+#include <vector>
+
+namespace android {
+
+Annotation::Annotation(
+ const char *name,
+ KeyedVector<std::string, std::vector<std::string> *> *params)
+ : mName(name),
+ mParamsByName(params) {
+}
+
+std::string Annotation::name() const {
+ return mName;
+}
+
+void Annotation::dump(Formatter &out) const {
+ out << "@" << mName;
+
+ if (mParamsByName->size() == 0) {
+ return;
+ }
+
+ out << "(";
+
+ for (size_t i = 0; i < mParamsByName->size(); ++i) {
+ if (i > 0) {
+ out << ", ";
+ }
+
+ out << mParamsByName->keyAt(i) << "=";
+
+ const std::vector<std::string> *param = mParamsByName->valueAt(i);
+ if (param->size() > 1) {
+ out << "{";
+ }
+
+ bool first = true;
+ for (const auto &value : *param) {
+ if (!first) {
+ out << ", ";
+ }
+
+ out << value;
+
+ first = false;
+ }
+
+ if (param->size() > 1) {
+ out << "}";
+ }
+ }
+
+ out << ")";
+}
+
+} // namespace android
+
diff --git a/Annotation.h b/Annotation.h
new file mode 100644
index 0000000..ad98bf9
--- /dev/null
+++ b/Annotation.h
@@ -0,0 +1,32 @@
+#ifndef ANNOTATION_H_
+
+#define ANNOTATION_H_
+
+#include <android-base/macros.h>
+
+#include <string>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct Formatter;
+
+struct Annotation {
+ Annotation(
+ const char *name,
+ KeyedVector<std::string, std::vector<std::string> *> *params);
+
+ std::string name() const;
+
+ void dump(Formatter &out) const;
+
+private:
+ std::string mName;
+ KeyedVector<std::string, std::vector<std::string> *> *mParamsByName;
+
+ DISALLOW_COPY_AND_ASSIGN(Annotation);
+};
+
+} // namespace android
+
+#endif // ANNOTATION_H_
diff --git a/Method.cpp b/Method.cpp
index 7e0058f..2569701 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -1,17 +1,19 @@
#include "Method.h"
+#include "Annotation.h"
#include "Formatter.h"
#include "Type.h"
namespace android {
-Method::Method(
- const char *name,
- std::vector<TypedVar *> *args,
- std::vector<TypedVar *> *results)
+Method::Method(const char *name,
+ std::vector<TypedVar *> *args,
+ std::vector<TypedVar *> *results,
+ KeyedVector<std::string, Annotation *> *annotations)
: mName(name),
mArgs(args),
- mResults(results) {
+ mResults(results),
+ mAnnotationsByName(annotations) {
}
std::string Method::name() const {
@@ -26,6 +28,10 @@
return *mResults;
}
+const KeyedVector<std::string, Annotation *> &Method::annotations() const {
+ return *mAnnotationsByName;
+}
+
// static
std::string Method::GetSignature(const std::vector<TypedVar *> &args) {
bool first = true;
@@ -47,6 +53,21 @@
return out;
}
+void Method::dumpAnnotations(Formatter &out) const {
+ if (mAnnotationsByName->size() == 0) {
+ return;
+ }
+
+ out << "// ";
+ for (size_t i = 0; i < mAnnotationsByName->size(); ++i) {
+ if (i > 0) {
+ out << " ";
+ }
+ mAnnotationsByName->valueAt(i)->dump(out);
+ }
+ out << "\n";
+}
+
////////////////////////////////////////////////////////////////////////////////
TypedVar::TypedVar(const char *name, Type *type)
diff --git a/Method.h b/Method.h
index a4e13d4..86c8f50 100644
--- a/Method.h
+++ b/Method.h
@@ -4,10 +4,12 @@
#include <android-base/macros.h>
#include <string>
+#include <utils/KeyedVector.h>
#include <vector>
namespace android {
+struct Annotation;
struct Formatter;
struct Type;
struct TypedVar;
@@ -15,18 +17,23 @@
struct Method {
Method(const char *name,
std::vector<TypedVar *> *args,
- std::vector<TypedVar *> *results = NULL);
+ std::vector<TypedVar *> *results,
+ KeyedVector<std::string, Annotation *> *annotations);
std::string name() const;
const std::vector<TypedVar *> &args() const;
const std::vector<TypedVar *> &results() const;
+ const KeyedVector<std::string, Annotation *> &annotations() const;
static std::string GetSignature(const std::vector<TypedVar *> &args);
+ void dumpAnnotations(Formatter &out) const;
+
private:
std::string mName;
std::vector<TypedVar *> *mArgs;
std::vector<TypedVar *> *mResults;
+ KeyedVector<std::string, Annotation *> *mAnnotationsByName;
DISALLOW_COPY_AND_ASSIGN(Method);
};
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 8e6da68..f871fd8 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -237,6 +237,8 @@
for (const auto &method : iface->methods()) {
const bool returnsValue = !method->results().empty();
+ method->dumpAnnotations(out);
+
out << "virtual ::android::hardware::Status "
<< method->name()
<< "("
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index 13ab222..359c351 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -13,6 +13,7 @@
%{
+#include "Annotation.h"
#include "AST.h"
#include "CompoundType.h"
#include "EnumType.h"
@@ -92,6 +93,7 @@
"." { count(yyg); return('.'); }
"=" { count(yyg); return('='); }
"+" { count(yyg); return('+'); }
+"@" { count(yyg); return('@'); }
{PATH}{VERSION}?"::"{PATH} { count(yyg); yylval->str = strdup(yytext); return FQNAME; }
{VERSION}"::"{PATH} { count(yyg); yylval->str = strdup(yytext); return FQNAME; }
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 4f640ce..0b1cd90 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -1,5 +1,6 @@
%{
+#include "Annotation.h"
#include "AST.h"
#include "ArrayType.h"
#include "CompoundType.h"
@@ -69,6 +70,11 @@
%type<typedVar> typed_var
%type<method> method_declaration
%type<compoundStyle> struct_or_union_keyword
+%type<stringVec> annotation_string_values annotation_value
+%type<annotationParam> annotation_param
+%type<annotationParams> opt_annotation_params annotation_params
+%type<annotation> annotation
+%type<annotations> opt_annotations
%start program
@@ -84,11 +90,87 @@
std::vector<android::TypedVar *> *typedVars;
android::Method *method;
android::CompoundType::Style compoundStyle;
- android::Vector<std::string> *stringVec;
+ std::vector<std::string> *stringVec;
+ std::pair<std::string, std::vector<std::string> *> *annotationParam;
+ android::KeyedVector<std::string, std::vector<std::string> *> *annotationParams;
+ android::Annotation *annotation;
+ android::KeyedVector<std::string, android::Annotation *> *annotations;
}
%%
+opt_annotations
+ : /* empty */
+ {
+ $$ = new KeyedVector<std::string, Annotation *>;
+ }
+ | opt_annotations annotation
+ {
+ $$ = $1;
+ $$->add($2->name(), $2);
+ }
+ ;
+
+annotation
+ : '@' IDENTIFIER opt_annotation_params
+ {
+ $$ = new Annotation($2, $3);
+ }
+ ;
+
+opt_annotation_params
+ : /* empty */
+ {
+ $$ = new KeyedVector<std::string, std::vector<std::string> *>;
+ }
+ | '(' annotation_params ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+annotation_params
+ : annotation_param
+ {
+ $$ = new KeyedVector<std::string, std::vector<std::string> *>;
+ $$->add($1->first, $1->second);
+ }
+ | annotation_params ',' annotation_param
+ {
+ $$ = $1;
+ $$->add($3->first, $3->second);
+ }
+ ;
+
+annotation_param
+ : IDENTIFIER '=' annotation_value
+ {
+ $$ = new std::pair<std::string, std::vector<std::string> *>($1, $3);
+ }
+ ;
+
+annotation_value
+ : STRING_LITERAL
+ {
+ $$ = new std::vector<std::string>;
+ $$->push_back($1);
+ }
+ | '{' annotation_string_values '}' { $$ = $2; }
+ ;
+
+annotation_string_values
+ : STRING_LITERAL
+ {
+ $$ = new std::vector<std::string>;
+ $$->push_back($1);
+ }
+ | annotation_string_values ',' STRING_LITERAL
+ {
+ $$ = $1;
+ $$->push_back($3);
+ }
+ ;
+
program
: package imports body
;
@@ -226,13 +308,13 @@
;
method_declaration
- : IDENTIFIER '(' typed_vars ')' ';'
+ : opt_annotations IDENTIFIER '(' typed_vars ')' ';'
{
- $$ = new Method($1, $3, new std::vector<TypedVar *>);
+ $$ = new Method($2, $4, new std::vector<TypedVar *>, $1);
}
- | IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
+ | opt_annotations IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
{
- $$ = new Method($1, $3, $7);
+ $$ = new Method($2, $4, $8, $1);
}
;