Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated enum for oneof message inconsistent with Style Guide #466

Closed
jcooper-korg opened this issue Jun 5, 2015 · 19 comments
Closed

Generated enum for oneof message inconsistent with Style Guide #466

jcooper-korg opened this issue Jun 5, 2015 · 19 comments
Assignees

Comments

@jcooper-korg
Copy link

oneof oneof_name {
    int32 foo_int = 4;
    string foo_string = 9;
}

generates the following:

enum OneofNameCase {
  kFooInt = 4,
  kFooString = 9,
  ONEOF_NAME_NOT_SET = 0
}

Why does the generated enum for a oneof message break the Style Guide naming rules for enum's?
The enum's should be CAPITALS_WITH_UNDERSCORES. Instead the oneof enum introduces a new kCamelCase style, but isn't even consistent with itself, since it includes ONEOF__NOT_SET.

The result is just a hodgepodge of styles- not very clean.

I guess google can't change this now without breaking current oneof code, but you could modify protoc to generate an additional enum for (or #defines) for each oneof to allow the proper naming style to be used in new code.

@jcooper-korg
Copy link
Author

This is frustrating for those of us that implemented unions per the previous recommended technique and style guide:
https://developers.google.com/protocol-buffers/docs/techniques#union
but are transitioning this code to use oneof instead.

@xfxyjwf
Copy link
Contributor

xfxyjwf commented Jun 5, 2015

@anandolee , do you know why we didn't use CAPITALS_WITH_UNDERSCORES for oneof enum names?

@jcooper-korg
Copy link
Author

One option would be to modify the oneof_decl loop in cpp_message.cc void MessageGenerator:: GenerateClassDefinition(io::Printer* printer) (and equivalent for other language generators) :

    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
      printer->Print(
          "k$field_name$ = $field_number$,\n",
          "field_name",
          UnderscoresToCamelCase(
              descriptor_->oneof_decl(i)->field(j)->name(), true),
          "field_number",
          SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number()));
    }

to simply duplicate this printer->Print call for each oneof_decl, but use a ToUpperCase instead of UnderscoresToCamelCase. So the resulting enum would look like

enum OneofNameCase {
  kFooInt = 4,
  FOO_INT = 4,
  kFooString = 9,
  FOO_STRING = 9,
  ONEOF_NAME_NOT_SET = 0
}

@anandolee
Copy link
Contributor

Not sure for the reason.

Use alias make sense to me

2015-06-05 10:40 GMT-07:00 Feng Xiao notifications@github.com:

@anandolee https://github.com/anandolee , do you know why we didn't use
CAPITALS_WITH_UNDERSCORES for oneof enum names?


Reply to this email directly or view it on GitHub
#466 (comment).

@jcooper-korg
Copy link
Author

Ok - to alias the enum's, I simply modified the loop at line 962 of cpp_messages.cc to do a second print, without the "k" in front and ToUpper instead of UnderscoresToCamelCase:

   for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
      // print like "kFooBar = N,"
      printer->Print(
          "k$field_name$ = $field_number$,\n",
          "field_name",
          UnderscoresToCamelCase(
              descriptor_->oneof_decl(i)->field(j)->name(), true),
          "field_number",
          SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number()));

      // also print an alias like "FOO_BAR = N,"
      printer->Print(
          "$field_name$ = $field_number$,\n",
          "field_name",
          ToUpper(descriptor_->oneof_decl(i)->field(j)->name()),
          "field_number",
          SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number()));
   }

Sound ok?

@jcooper-korg
Copy link
Author

I'm curious- will this fix be included in the next protobuf release?

@anandolee
Copy link
Contributor

Sorry for late update. I read the style guide again, macro-style naming is required in .proto file. But the generate code is c++ file which should follow c++ style guide instead of .proto style. For c++ file, enumerators should be named either like constants or like macros.

For c++, "the style was to name enum values like macros. This caused problems with name collisions between enum values and macros. Hence, the change to prefer constant-style naming was put in place. New code should prefer constant-style naming if possible. However, there is no reason to change old code to use constant-style names, unless the old names are actually causing a compile-time problem."

I think current code which mixed the two style is still not good. However, it makes a little sense to difference set and not set.

@jcooper-korg
Copy link
Author

Thank you for the response. I don't totally agree with the distinction that generated C++ code should use kConstantStyle naming, while proto enum names should use MACRO_STYLE. The enums in the proto files are MACRO_STYLE, and result in generated C++ enumerations that are also MACRO_STYLE - they are not converted to google-C++-style-guide kConstantStyle naming. It really doesn't make much sense to have it both ways.
I could understand your argument if the generated enums for oneof were internal and private to the generated code. However, we must use these generated enum's in our public code. Since the proto style guide says to use MACRO_STYLE for enumerations, we have written all our code to use that style. But now, using oneof, the generated enums are inconsistent.
Forfeiting naming consistency to avoid namespace collisions with other macros seems rather arbitrary. I have made my suggested modification in our code to produce both the constant and macro style names for generated oneof enums, and we don't have a single case of a namespace collision, over thousands of instances.
Would you still consider my modification to cpp_messages.cc, for a public release?
Thanks for your consideration.

@anandolee
Copy link
Contributor

" I have made my suggested modification in our code " Where did you make the change? On opensource or google internal?

@pherl Do you think is it OK to add alias even c++ style prefer to use constant-style to avoid name collisions?
https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Enumerator_Names

jcooper-korg added a commit to jcooper-korg/protobuf that referenced this issue Jul 22, 2015
Work around google proto3 oneof enum naming inconsistency issue.  Generate a MACRO_STYLE alias for each oneof enum value, in addition to the kCamelCaseStyle value. For example:
   oneof oneof_name {
       int32 foo_int = 4;
       string foo_string = 9;
   }
Will generate the following:
   enum OneofNameCase {
       kFooInt = 4,
       FOO_INT = 4,
       kFooString = 9,
       FOO_STRING = 9,
       ONEOF_NAME_NOT_SET = 0
   }
@jcooper-korg
Copy link
Author

I just forked and pushed the change:
jcooper-korg@841fda4
Shall I send a pul request?

@jcooper-korg
Copy link
Author

Just following up. Didn't see a response from @pherl or @anandolee.
Thanks

@liujisi
Copy link
Contributor

liujisi commented Jul 30, 2015

Hmm, generating two styles seem to diverge the API further. @anandolee could you check how many internal use cases are there? We could probably clean those up and switch to the macro style.

@anandolee
Copy link
Contributor

Will look into it.

@anandolee
Copy link
Contributor

Just looked into internal use cases, where are more than 10k uses already. It will be hard to clean those up and switch to macro style...
Generate both will diverge the API further as @pherl mentioned. @jcooper-korg is it possible to change your usage to constant-style?

@jcooper-korg
Copy link
Author

@pherl: why would this diverge the API? the API doesn't change - but the user would have a choice of naming style for oneof C++ generated enum's
@anandolee: I understand. We have 1000's of cases also, which is why I'm reluctant to change it.
Worst case, we can maintain our own fork of protobuf.

@liujisi
Copy link
Contributor

liujisi commented Jul 30, 2015

It diverges the style that users would use the API. I'd rather not introduce such variation/inconsistency.

@jcooper-korg
Copy link
Author

@pherl: The original point of this issue was that the naming style of the C++ generated oneof enums is inconsistent with everything else in protobuf.

@liujisi
Copy link
Contributor

liujisi commented Jul 30, 2015

Having two symbol names for the same value seems problematic to me. Clients could use either of them even in a single project, which hurts the readability. I am fine with going with macro style or const style, however, generating aliasing values that allows two dialects is worse than either of the style.

@acozzette
Copy link
Member

I am going to go ahead and close this because we are cleaning up issues and I see that this one has not been updated in a long time. Feel free to reopen it if this is still a problem, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants