Commit ec19be2f authored by Jeff Davidson's avatar Jeff Davidson Committed by Brian Duff

Generate @IntDef annotations for nanoproto enums.

@IntDef is a support library annotation which allows build tools to
determine the valid set of values for a given integer field when that
field is intended to be restricted like an enum. This avoids the
overhead of enums while still allowing for compile-time type checking
in most circumstances.

Change-Id: Iee02e0b49a8e069f6456572f538e0a0d301fdfd5
parent 41f0294c
......@@ -145,6 +145,7 @@ optional_field_style -> default or accessors
enum_style -> c or java
ignore_services -> true or false
parcelable_messages -> true or false
generate_intdefs -> true or false
```
**java_package=\<file-name\>|\<package-name\>** (no default)
......@@ -302,6 +303,28 @@ parcelable_messages -> true or false
Android-specific option to generate Parcelable messages.
**generate_intdefs={true,false}** (default: false)
Android-specific option to generate @IntDef annotations for enums.
If turned on, an '@IntDef' annotation (a public @interface) will be
generated for each enum, and every integer parameter and return
value in the generated code meant for this enum will be annotated
with it. This interface is generated with the same name and at the
same place as the enum members' container interfaces described
above under 'enum_style=java', regardless of the enum_style option
used. When this is combined with enum_style=java, the interface
will be both the '@IntDef' annotation and the container of the enum
members; otherwise the interface has an empty body.
Your app must declare a compile-time dependency on the
android-support-annotations library.
For more information on how these @IntDef annotations help with
compile-time type safety, see:
https://sites.google.com/a/android.com/tools/tech-docs/support-annotations
and
https://developer.android.com/reference/android/support/annotation/IntDef.html
To use nano protobufs within the Android repo:
----------------------------------------------
......
......@@ -73,13 +73,45 @@ void EnumGenerator::Generate(io::Printer* printer) {
"// enum $classname$\n",
"classname", descriptor_->name());
const string classname = RenameJavaKeywords(descriptor_->name());
// Start of container interface
// If generating intdefs, we use the container interface as the intdef if
// present. Otherwise, we just make an empty @interface parallel to the
// constants.
bool use_intdef = params_.generate_intdefs();
bool use_shell_class = params_.java_enum_style();
if (use_shell_class) {
printer->Print(
"public interface $classname$ {\n",
"classname", RenameJavaKeywords(descriptor_->name()));
if (use_intdef) {
// @IntDef annotation so tools can enforce correctness
// Annotations will be discarded by the compiler
printer->Print("@java.lang.annotation.Retention("
"java.lang.annotation.RetentionPolicy.SOURCE)\n"
"@android.support.annotation.IntDef({\n");
printer->Indent();
for (int i = 0; i < canonical_values_.size(); i++) {
const string constant_name =
RenameJavaKeywords(canonical_values_[i]->name());
if (use_shell_class) {
printer->Print("$classname$.$name$,\n",
"classname", classname,
"name", constant_name);
} else {
printer->Print("$name$,\n", "name", constant_name);
}
}
printer->Outdent();
printer->Print("})\n");
}
if (use_shell_class || use_intdef) {
printer->Print(
"public $at_for_intdef$interface $classname$ {\n",
"classname", classname,
"at_for_intdef", use_intdef ? "@" : "");
if (use_shell_class) {
printer->Indent();
} else {
printer->Print("}\n\n");
}
}
// Canonical values
......
......@@ -76,6 +76,10 @@ void SetEnumVariables(const Params& params,
internal::WireFormatLite::MakeTag(descriptor->number(),
internal::WireFormat::WireTypeForFieldType(descriptor->type())));
(*variables)["message_name"] = descriptor->containing_type()->name();
const EnumDescriptor* enum_type = descriptor->enum_type();
(*variables)["message_type_intdef"] = "@"
+ ToJavaName(params, enum_type->name(), true,
enum_type->containing_type(), enum_type->file());
}
void LoadEnumValues(const Params& params,
......@@ -116,8 +120,10 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_,
"public $type$ $name$;\n");
if (params_.generate_intdefs()) {
printer->Print(variables_, "$message_type_intdef$\n");
}
printer->Print(variables_, "public $type$ $name$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
......@@ -256,12 +262,22 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
printer->Print(variables_, "private int $name$_;\n");
if (params_.generate_intdefs()) {
printer->Print(variables_, "$message_type_intdef$\n");
}
printer->Print(variables_,
"private int $name$_;\n"
"public int get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public $message_name$ set$capitalized_name$(int value) {\n"
"public $message_name$ set$capitalized_name$(");
if (params_.generate_intdefs()) {
printer->Print(variables_,
"\n"
" $message_type_intdef$ ");
}
printer->Print(variables_,
"int value) {\n"
" $name$_ = value;\n"
" $set_has$;\n"
" return this;\n"
......
......@@ -154,6 +154,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
params.set_parcelable_messages(option_value == "true");
} else if (option_name == "generate_clone") {
params.set_generate_clone(option_value == "true");
} else if (option_name == "generate_intdefs") {
params.set_generate_intdefs(option_value == "true");
} else {
*error = "Ignore unknown javanano generator option: " + option_name;
}
......
......@@ -67,6 +67,7 @@ class Params {
bool reftypes_primitive_enums_;
bool generate_clear_;
bool generate_clone_;
bool generate_intdefs_;
public:
Params(const string & base_name) :
......@@ -83,7 +84,8 @@ class Params {
parcelable_messages_(false),
reftypes_primitive_enums_(false),
generate_clear_(true),
generate_clone_(false) {
generate_clone_(false),
generate_intdefs_(false) {
}
const string& base_name() const {
......@@ -240,6 +242,13 @@ class Params {
bool generate_clone() const {
return generate_clone_;
}
void set_generate_intdefs(bool value) {
generate_intdefs_ = value;
}
bool generate_intdefs() const {
return generate_intdefs_;
}
};
} // namespace javanano
......
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