summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Davidson <jpd@google.com>2015-02-11 13:12:14 -0800
committerJeff Davidson <jpd@google.com>2015-02-19 19:55:26 +0000
commit30d873bd66f50a6021de5d44d7ee5b8a809b0524 (patch)
treec4cec97120f5b387aa9ea6910ff1e839725ccfb8
parenteb5ae9e258a8fc953e6cf0b3a0dd04a112a05a3c (diff)
downloadexternal_protobuf-30d873bd66f50a6021de5d44d7ee5b8a809b0524.zip
external_protobuf-30d873bd66f50a6021de5d44d7ee5b8a809b0524.tar.gz
external_protobuf-30d873bd66f50a6021de5d44d7ee5b8a809b0524.tar.bz2
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
-rw-r--r--Android.mk8
-rw-r--r--java/README.txt24
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc40
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc24
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_params.h11
6 files changed, 98 insertions, 11 deletions
diff --git a/Android.mk b/Android.mk
index fcf9a21..5dc957c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -462,6 +462,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE := android-nano-test-parcelable
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
+# Only needed at compile-time.
+LOCAL_JAVA_LIBRARIES := android-support-annotations
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
@@ -470,7 +472,8 @@ LOCAL_SRC_FILES := src/google/protobuf/unittest_simple_nano.proto
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
- parcelable_messages = true
+ parcelable_messages = true, \
+ generate_intdefs = true
include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -480,6 +483,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE := android-nano-test-parcelable-extendable
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
+# Only needed at compile-time.
+LOCAL_JAVA_LIBRARIES := android-support-annotations
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
@@ -489,6 +494,7 @@ LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
parcelable_messages = true, \
+ generate_intdefs = true, \
store_unknown_fields = true
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/java/README.txt b/java/README.txt
index 7081a84..b02e88b 100644
--- a/java/README.txt
+++ b/java/README.txt
@@ -593,6 +593,28 @@ ignore_services={true,false} (default: false)
parcelable_messages={true,false} (default: 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:
@@ -646,7 +668,7 @@ Please run the following steps to test:
- "make -j12 aprotoc libprotobuf-java-nano aprotoc-test-nano-params NanoAndroidTest" and
check for build errors.
- Plug in an Android device or start an emulator.
-- adb install -r out/target/product/generic/data/app/NanoAndroidTest.apk
+- adb install -r out/target/product/generic/data/app/NanoAndroidTest/NanoAndroidTest.apk
- Run:
"adb shell am instrument -w com.google.protobuf.nano.test/android.test.InstrumentationTestRunner"
and verify all tests pass.
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
index f934b05..c6e8dfe 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -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
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
index 99b316b..7666db3 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -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"
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index 9ca06cd..96e3e80 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -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;
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
index 77bc717..e3b4bb9 100644
--- a/src/google/protobuf/compiler/javanano/javanano_params.h
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -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