google / protobuf.dart

Runtime library for Dart protobufs
https://pub.dev/packages/protobuf
BSD 3-Clause "New" or "Revised" License
533 stars 184 forks source link

Dart enums generated by protoc don't follow dart naming conventions #372

Open pikaju opened 4 years ago

pikaju commented 4 years ago

When giving a protobuf enum a scream case name, it will remain scream case in the generated Dart code, even though this does not match the Dart standard.

blindmatrix commented 2 years ago

Any updates on this?

osa1 commented 2 years ago

Just to make sure I understand the issue correctly, currently for this proto:

enum CamelCaseEnumName {
  _x = 0;
  _Y = 1;
  Z_ = 2;
  A_A = 4;
  b_b = 5;
  camelCase = 6;
  SNAKE_CASE = 7;
}

We generate this Dart:

///
//  Generated code. Do not modify.
//  source: enum_name.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,constant_identifier_names,directives_ordering,library_prefixes,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name

// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;

class CamelCaseEnumName extends $pb.ProtobufEnum {
  static const CamelCaseEnumName x_ = CamelCaseEnumName._(0,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : '_x');
  static const CamelCaseEnumName Y_ = CamelCaseEnumName._(1,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : '_Y');
  static const CamelCaseEnumName Z_ = CamelCaseEnumName._(2,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Z_');
  static const CamelCaseEnumName A_A = CamelCaseEnumName._(
      4,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names')
          ? ''
          : 'A_A');
  static const CamelCaseEnumName b_b = CamelCaseEnumName._(
      5,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names')
          ? ''
          : 'b_b');
  static const CamelCaseEnumName camelCase = CamelCaseEnumName._(
      6,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names')
          ? ''
          : 'camelCase');
  static const CamelCaseEnumName SNAKE_CASE = CamelCaseEnumName._(
      7,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names')
          ? ''
          : 'SNAKE_CASE');

  static const $core.List<CamelCaseEnumName> values = <CamelCaseEnumName>[
    x_,
    Y_,
    Z_,
    A_A,
    b_b,
    camelCase,
    SNAKE_CASE,
  ];

  static final $core.Map<$core.int, CamelCaseEnumName> _byValue =
      $pb.ProtobufEnum.initByValue(values);
  static CamelCaseEnumName? valueOf($core.int value) => _byValue[value];

  const CamelCaseEnumName._($core.int v, $core.String n) : super(v, n);
}

This has a ignore_for_file directive for constant_identifier_names so no warnings generated here or in the use sites for non-camel-case constants.

So the problem here is inconsistency in constant names in the use sites of generated enum values.

Is this a right description of the problem?


Assuming I understand the problem correctly, to avoid breakage we can initially deprecate the old, non-camel-case variables and redirect users to the new ones. For example, in the example above, we can generate this:

  @$core.Deprecated('Use `snakeCase` instead, see protobuf.dart issue #372')
  static const CamelCaseEnumName SNAKE_CASE = snakeCase;

  static const snakeCase = CamelCaseEnumName._(
      7,
      const $core.bool.fromEnvironment('protobuf.omit_enum_names')
          ? ''
          : 'SNAKE_CASE');

Then remove the deprecated variables in the future.

One question is how to map proto values to Dart const variables when the camel case versions of the names conflict. For example:

enum A {
  MY_VALUE = 1;
  myValue = 2;
}

Both of those are mapped to Dart myValue. We will have to add a _ or something like that to one of these values in Dart, but we need to make it clear to the user which one is mapped to which proto value. I.e. maybe in the example above myValue will be for the original MY_VALUE, myValue_ will be for the original myValue.