From 30d873bd66f50a6021de5d44d7ee5b8a809b0524 Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Wed, 11 Feb 2015 13:12:14 -0800 Subject: 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 --- .../protobuf/compiler/javanano/javanano_enum.cc | 40 +++++++++++++++++++--- .../compiler/javanano/javanano_enum_field.cc | 24 ++++++++++--- .../compiler/javanano/javanano_generator.cc | 2 ++ .../protobuf/compiler/javanano/javanano_params.h | 11 +++++- 4 files changed, 68 insertions(+), 9 deletions(-) (limited to 'src') 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 -- cgit v1.1