diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index 19f39575c7..5a04b6f1fd 100644 --- a/java/src/test/java/com/google/protobuf/NanoTest.java +++ b/java/src/test/java/com/google/protobuf/NanoTest.java @@ -2250,6 +2250,12 @@ public class NanoTest extends TestCase { assertEquals(message.d, newMessage.d); } + public void testJavaKeyword() throws Exception { + TestAllTypesNano msg = new TestAllTypesNano(); + msg.synchronized_ = 123; + assertEquals(123, msg.synchronized_); + } + private List list(T first, T... remaining) { List list = new ArrayList(); list.add(first); diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index 6ba25ebdc7..66b671b159 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -82,7 +82,7 @@ void EnumGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < canonical_values_.size(); i++) { map vars; - vars["name"] = canonical_values_[i]->name(); + vars["name"] = RenameJavaKeywords(canonical_values_[i]->name()); vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number()); printer->Print(vars, "public static final int $name$ = $canonical_value$;\n"); @@ -92,7 +92,7 @@ void EnumGenerator::Generate(io::Printer* printer) { for (int i = 0; i < aliases_.size(); i++) { map vars; - vars["name"] = aliases_[i].value->name(); + vars["name"] = RenameJavaKeywords(aliases_[i].value->name()); vars["canonical_name"] = aliases_[i].canonical_value->name(); printer->Print(vars, "public static final int $name$ = $canonical_name$;\n"); diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index a22aa6fd06..215f341989 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -54,9 +54,9 @@ namespace { void SetEnumVariables(const Params& params, const FieldDescriptor* descriptor, map* variables) { (*variables)["name"] = - UnderscoresToCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["type"] = "int"; (*variables)["default"] = DefaultValue(params, descriptor); diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc index ea74af9ca6..a85645e927 100644 --- a/src/google/protobuf/compiler/javanano/javanano_extension.cc +++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc @@ -45,7 +45,8 @@ using internal::WireFormat; void SetVariables(const FieldDescriptor* descriptor, const Params params, map* variables) { - (*variables)["name"] = UnderscoresToCamelCase(descriptor); + (*variables)["name"] = + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["extends"] = ClassName(params, descriptor->containing_type()); diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 42cb133913..80ee7a043b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,48 @@ const char kThickSeparator[] = const char kThinSeparator[] = "// -------------------------------------------------------------------\n"; +class RenameKeywords { + private: + hash_set java_keywords_set_; + + public: + RenameKeywords() { + static const char* kJavaKeywordsList[] = { + // Reserved Java Keywords + "abstract", "assert", "boolean", "break", "byte", "case", "catch", + "char", "class", "const", "continue", "default", "do", "double", "else", + "enum", "extends", "final", "finally", "float", "for", "goto", "if", + "implements", "import", "instanceof", "int", "interface", "long", + "native", "new", "package", "private", "protected", "public", "return", + "short", "static", "strictfp", "super", "switch", "synchronized", + "this", "throw", "throws", "transient", "try", "void", "volatile", "while", + + // Reserved Keywords for Literals + "false", "null", "true" + }; + + for (int i = 0; i < GOOGLE_ARRAYSIZE(kJavaKeywordsList); i++) { + java_keywords_set_.insert(kJavaKeywordsList[i]); + } + } + + // Used to rename the a field name if it's a java keyword. Specifically + // this is used to rename the ["name"] or ["capitalized_name"] field params. + // (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html) + string RenameJavaKeywordsImpl(const string& input) { + string result = input; + + if (java_keywords_set_.find(result) != java_keywords_set_.end()) { + result += "_"; + } + + return result; + } + +}; + +static RenameKeywords sRenameKeywords; + namespace { const char* kDefaultPackage = ""; @@ -110,6 +153,10 @@ string UnderscoresToCamelCase(const MethodDescriptor* method) { return UnderscoresToCamelCaseImpl(method->name(), false); } +string RenameJavaKeywords(const string& input) { + return sRenameKeywords.RenameJavaKeywordsImpl(input); +} + string StripProto(const string& filename) { if (HasSuffixString(filename, ".protodevel")) { return StripSuffixString(filename, ".protodevel"); diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index 04e0c2e9d4..afadf60848 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -55,6 +55,10 @@ extern const char kThinSeparator[]; string UnderscoresToCamelCase(const FieldDescriptor* field); string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); +// Appends an "_" to the end of a field where the name is a reserved java +// keyword. For example int32 public = 1 will generate int public_. +string RenameJavaKeywords(const string& input); + // Similar, but for method names. (Typically, this merely has the effect // of lower-casing the first letter of the name.) string UnderscoresToCamelCase(const MethodDescriptor* method); diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 11fb452603..90ae0417f6 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -396,12 +396,12 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { // type. printer->Print( "$name$ = $default$.clone();\n", - "name", UnderscoresToCamelCase(field), + "name", RenameJavaKeywords(UnderscoresToCamelCase(field)), "default", DefaultValue(params_, field)); } else { printer->Print( "$name$ = $default$;\n", - "name", UnderscoresToCamelCase(field), + "name", RenameJavaKeywords(UnderscoresToCamelCase(field)), "default", DefaultValue(params_, field)); } } diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index ec9d995f18..7d9a281e9e 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -56,9 +56,9 @@ namespace { void SetMessageVariables(const Params& params, const FieldDescriptor* descriptor, map* variables) { (*variables)["name"] = - UnderscoresToCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["type"] = ClassName(params, descriptor->message_type()); (*variables)["group_or_message"] = diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 1cf9066295..a8afe942b9 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -208,9 +208,9 @@ bool AllAscii(const string& text) { void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, map* variables) { (*variables)["name"] = - UnderscoresToCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); + RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["default"] = DefaultValue(params, descriptor); diff --git a/src/google/protobuf/unittest_nano.proto b/src/google/protobuf/unittest_nano.proto index 62af6bc48f..e9a0d83361 100644 --- a/src/google/protobuf/unittest_nano.proto +++ b/src/google/protobuf/unittest_nano.proto @@ -157,6 +157,9 @@ message TestAllTypesNano { optional int32 tag = 93; optional int32 get_serialized_size = 94; optional int32 write_to = 95; + + // Try to fail with java reserved keywords + optional int32 synchronized = 96; } message ForeignMessageNano {