Avoid name collisions with Int64 and enum names beginning with digits. (#299)
* Avoid name collisions with Int64 and enum names beginning with digits.
diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index 67fa524..a7d6a3f 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 19.0.1
+
+* Fix: avoid naming collisions with `Int64` and enum names beginning with digits
+ after an initial underscore.
+
## 19.0.0+1
* Updated protobuf dependency to '>=0.14.4 <2.0.0' to allow 1.0.0.
diff --git a/protoc_plugin/lib/base_type.dart b/protoc_plugin/lib/base_type.dart
index 8c98f67..d447ce3 100644
--- a/protoc_plugin/lib/base_type.dart
+++ b/protoc_plugin/lib/base_type.dart
@@ -85,19 +85,19 @@
"SF3", "$_coreImportPrefix.int", r"$_setSignedInt32", null);
case FieldDescriptorProto_Type.TYPE_INT64:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_INT64, "6",
- "Int64", r"$_setInt64", null);
+ "$_fixnumImportPrefix.Int64", r"$_setInt64", null);
case FieldDescriptorProto_Type.TYPE_UINT64:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_UINT64, "U6",
- "Int64", r"$_setInt64", null);
+ "$_fixnumImportPrefix.Int64", r"$_setInt64", null);
case FieldDescriptorProto_Type.TYPE_SINT64:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_SINT64, "S6",
- "Int64", r"$_setInt64", null);
+ "$_fixnumImportPrefix.Int64", r"$_setInt64", null);
case FieldDescriptorProto_Type.TYPE_FIXED64:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_FIXED64, "F6",
- "Int64", r"$_setInt64", null);
+ "$_fixnumImportPrefix.Int64", r"$_setInt64", null);
case FieldDescriptorProto_Type.TYPE_SFIXED64:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_SFIXED64,
- "SF6", "Int64", r"$_setInt64", null);
+ "SF6", "$_fixnumImportPrefix.Int64", r"$_setInt64", null);
case FieldDescriptorProto_Type.TYPE_STRING:
return const BaseType._raw(FieldDescriptorProto_Type.TYPE_STRING, "S",
"$_coreImportPrefix.String", r"$_setString", null);
diff --git a/protoc_plugin/lib/file_generator.dart b/protoc_plugin/lib/file_generator.dart
index 91c357c..7e27ba5 100644
--- a/protoc_plugin/lib/file_generator.dart
+++ b/protoc_plugin/lib/file_generator.dart
@@ -9,6 +9,7 @@
const String _protobufImportPrefix = r'$pb';
const String _asyncImportPrefix = r'$async';
const String _coreImportPrefix = r'$core';
+const String _fixnumImportPrefix = r'$fixnum';
const String _grpcImportPrefix = r'$grpc';
const String _mixinImportPrefix = r'$mixin';
const String _protobufImport =
@@ -290,7 +291,8 @@
out.println();
if (_needsFixnumImport) {
- out.println("import 'package:fixnum/fixnum.dart';");
+ out.println(
+ "import 'package:fixnum/fixnum.dart' as $_fixnumImportPrefix;");
}
if (_needsProtobufImport) {
diff --git a/protoc_plugin/lib/message_generator.dart b/protoc_plugin/lib/message_generator.dart
index 221d827..c4a6428 100644
--- a/protoc_plugin/lib/message_generator.dart
+++ b/protoc_plugin/lib/message_generator.dart
@@ -570,7 +570,7 @@
}
return '\$_getI($index, $defaultExpr)';
}
- if (fieldType == 'Int64' && defaultExpr == 'null') {
+ if (fieldType == '$_fixnumImportPrefix.Int64' && defaultExpr == 'null') {
return '\$_getI64($index)';
}
if (defaultExpr == 'null') {
diff --git a/protoc_plugin/lib/names.dart b/protoc_plugin/lib/names.dart
index 56bbf74..c712741 100644
--- a/protoc_plugin/lib/names.dart
+++ b/protoc_plugin/lib/names.dart
@@ -70,16 +70,24 @@
this.whichOneofMethodName, this.oneofEnumName, this.byTagMapName);
}
+// For performance reasons, use code units instead of Regex.
+bool _startsWithDigit(String input) =>
+ input.isNotEmpty && (input.codeUnitAt(0) ^ 0x30) <= 9;
+
/// Move any initial underscores in [input] to the end.
///
/// According to the spec identifiers cannot start with _, but it seems to be
-/// accepted by protoc.
+/// accepted by protoc. These identifiers are private in Dart, so they have to
+/// be transformed.
///
-/// These identifiers are private in Dart, so they have to be transformed.
+/// If [input] starts with a digit after transformation, prefix with an 'x'.
String avoidInitialUnderscore(String input) {
while (input.startsWith('_')) {
input = '${input.substring(1)}_';
}
+ if (_startsWithDigit(input)) {
+ input = 'x$input';
+ }
return input;
}
diff --git a/protoc_plugin/lib/protobuf_field.dart b/protoc_plugin/lib/protobuf_field.dart
index 2d9c79e..2d41875 100644
--- a/protoc_plugin/lib/protobuf_field.dart
+++ b/protoc_plugin/lib/protobuf_field.dart
@@ -81,7 +81,8 @@
_hasBooleanOption(Dart_options.overrideClearMethod);
/// True if this field uses the Int64 from the fixnum package.
- bool get needsFixnumImport => baseType.unprefixed == "Int64";
+ bool get needsFixnumImport =>
+ baseType.unprefixed == "$_fixnumImportPrefix.Int64";
/// True if this field is a map field definition:
/// `map<key_type, value_type> map_field = N`.
@@ -237,8 +238,8 @@
break;
}
} else {
- if (makeDefault == 'Int64.ZERO' &&
- type == 'Int64' &&
+ if (makeDefault == '$_fixnumImportPrefix.Int64.ZERO' &&
+ type == '$_fixnumImportPrefix.Int64' &&
typeConstant == '$_protobufImportPrefix.PbFieldType.O6') {
invocation = 'aInt64';
} else {
@@ -325,7 +326,7 @@
case FieldDescriptorProto_Type.TYPE_SFIXED64:
var value = '0';
if (descriptor.hasDefaultValue()) value = descriptor.defaultValue;
- if (value == '0') return 'Int64.ZERO';
+ if (value == '0') return '$_fixnumImportPrefix.Int64.ZERO';
return "$_protobufImportPrefix.parseLongInt('$value')";
case FieldDescriptorProto_Type.TYPE_STRING:
return _getDefaultAsStringExpr(null);
diff --git a/protoc_plugin/lib/src/descriptor.pb.dart b/protoc_plugin/lib/src/descriptor.pb.dart
index 59408ef..cddd9ed 100644
--- a/protoc_plugin/lib/src/descriptor.pb.dart
+++ b/protoc_plugin/lib/src/descriptor.pb.dart
@@ -7,7 +7,7 @@
import 'dart:core' as $core;
-import 'package:fixnum/fixnum.dart';
+import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
import 'descriptor.pbenum.dart';
@@ -1704,8 +1704,8 @@
..pc<UninterpretedOption_NamePart>(2, 'name', $pb.PbFieldType.PM,
subBuilder: UninterpretedOption_NamePart.create)
..aOS(3, 'identifierValue')
- ..a<Int64>(4, 'positiveIntValue', $pb.PbFieldType.OU6,
- defaultOrMaker: Int64.ZERO)
+ ..a<$fixnum.Int64>(4, 'positiveIntValue', $pb.PbFieldType.OU6,
+ defaultOrMaker: $fixnum.Int64.ZERO)
..aInt64(5, 'negativeIntValue')
..a<$core.double>(6, 'doubleValue', $pb.PbFieldType.OD)
..a<$core.List<$core.int>>(7, 'stringValue', $pb.PbFieldType.OY)
@@ -1749,9 +1749,9 @@
void clearIdentifierValue() => clearField(3);
@$pb.TagNumber(4)
- Int64 get positiveIntValue => $_getI64(2);
+ $fixnum.Int64 get positiveIntValue => $_getI64(2);
@$pb.TagNumber(4)
- set positiveIntValue(Int64 v) {
+ set positiveIntValue($fixnum.Int64 v) {
$_setInt64(2, v);
}
@@ -1761,9 +1761,9 @@
void clearPositiveIntValue() => clearField(4);
@$pb.TagNumber(5)
- Int64 get negativeIntValue => $_getI64(3);
+ $fixnum.Int64 get negativeIntValue => $_getI64(3);
@$pb.TagNumber(5)
- set negativeIntValue(Int64 v) {
+ set negativeIntValue($fixnum.Int64 v) {
$_setInt64(3, v);
}
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml
index 0e706af..a96bf41 100644
--- a/protoc_plugin/pubspec.yaml
+++ b/protoc_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
name: protoc_plugin
-version: 19.0.0+1
+version: 19.0.1
author: Dart Team <misc@dartlang.org>
description: Protoc compiler plugin to generate Dart code
homepage: https://github.com/dart-lang/protobuf
diff --git a/protoc_plugin/test/file_generator_test.dart b/protoc_plugin/test/file_generator_test.dart
index 12f0a94..84cf9c9 100644
--- a/protoc_plugin/test/file_generator_test.dart
+++ b/protoc_plugin/test/file_generator_test.dart
@@ -69,6 +69,22 @@
..defaultValue = r'$'
]));
}
+ return fd;
+}
+
+FileDescriptorProto createInt64Proto() {
+ FileDescriptorProto fd = FileDescriptorProto()..name = 'test';
+ fd.messageType.add(DescriptorProto()
+ ..name = 'Int64'
+ ..field.add(
+ // optional int64 value = 1;
+ FieldDescriptorProto()
+ ..name = 'value'
+ ..jsonName = 'value'
+ ..number = 1
+ ..label = FieldDescriptorProto_Label.LABEL_OPTIONAL
+ ..type = FieldDescriptorProto_Type.TYPE_INT64,
+ ));
return fd;
}
@@ -85,6 +101,16 @@
fg.generateMainFile().toString(), 'test/goldens/oneMessage.pb');
});
+ test('FileGenerator outputs a .pb.dart file for an Int64 message', () {
+ FileDescriptorProto fd = createInt64Proto();
+ var options =
+ parseGenerationOptions(CodeGeneratorRequest(), CodeGeneratorResponse());
+ FileGenerator fg = FileGenerator(fd, options);
+ link(options, [fg]);
+ expectMatchesGoldenFile(
+ fg.generateMainFile().toString(), 'test/goldens/int64.pb');
+ });
+
test(
'FileGenerator outputs a .pb.dart.meta file for a proto with one message',
() {
diff --git a/protoc_plugin/test/goldens/header_with_fixnum.pb b/protoc_plugin/test/goldens/header_with_fixnum.pb
index eb98d65..b5bc420 100644
--- a/protoc_plugin/test/goldens/header_with_fixnum.pb
+++ b/protoc_plugin/test/goldens/header_with_fixnum.pb
@@ -7,6 +7,6 @@
import 'dart:core' as $core;
-import 'package:fixnum/fixnum.dart';
+import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
diff --git a/protoc_plugin/test/goldens/int64.pb b/protoc_plugin/test/goldens/int64.pb
new file mode 100644
index 0000000..df1f41d
--- /dev/null
+++ b/protoc_plugin/test/goldens/int64.pb
@@ -0,0 +1,43 @@
+///
+// Generated code. Do not modify.
+// source: test
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:core' as $core;
+
+import 'package:fixnum/fixnum.dart' as $fixnum;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class Int64 extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('Int64', createEmptyInstance: create)
+ ..aInt64(1, 'value')
+ ..hasRequiredFields = false
+ ;
+
+ Int64._() : super();
+ factory Int64() => create();
+ factory Int64.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory Int64.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ Int64 clone() => Int64()..mergeFromMessage(this);
+ Int64 copyWith(void Function(Int64) updates) => super.copyWith((message) => updates(message as Int64));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static Int64 create() => Int64._();
+ Int64 createEmptyInstance() => create();
+ static $pb.PbList<Int64> createRepeated() => $pb.PbList<Int64>();
+ @$core.pragma('dart2js:noInline')
+ static Int64 getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Int64>(create);
+ static Int64 _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $fixnum.Int64 get value => $_getI64(0);
+ @$pb.TagNumber(1)
+ set value($fixnum.Int64 v) { $_setInt64(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasValue() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearValue() => clearField(1);
+}
+
diff --git a/protoc_plugin/test/leading_underscores_test.dart b/protoc_plugin/test/leading_underscores_test.dart
index 61c4aee..933d198 100644
--- a/protoc_plugin/test/leading_underscores_test.dart
+++ b/protoc_plugin/test/leading_underscores_test.dart
@@ -50,6 +50,9 @@
expect(messageA.e, Enum_.constant);
messageA.clearE();
expect(messageA.e, Enum_.default_);
+ messageA.clearE();
+ messageA.e = Enum_.x1digit_;
+ expect(messageA.e, Enum_.x1digit_);
messageA.r.add(message);
expect(messageA.r, [message]);
messageA.setExtension(Leading_underscores_.q, Int64(100));
diff --git a/protoc_plugin/test/names_test.dart b/protoc_plugin/test/names_test.dart
index 9a5372c..f8d2410 100644
--- a/protoc_plugin/test/names_test.dart
+++ b/protoc_plugin/test/names_test.dart
@@ -129,6 +129,8 @@
expect(names.avoidInitialUnderscore('foo_'), 'foo_');
expect(names.avoidInitialUnderscore('_foo'), 'foo_');
expect(names.avoidInitialUnderscore('__foo'), 'foo__');
+ expect(names.avoidInitialUnderscore('_6E'), 'x6E_');
+ expect(names.avoidInitialUnderscore('__6E'), 'x6E__');
});
test('legalDartIdentifier', () {
diff --git a/protoc_plugin/test/protos/_leading_underscores.proto b/protoc_plugin/test/protos/_leading_underscores.proto
index 49067ba..df91552 100644
--- a/protoc_plugin/test/protos/_leading_underscores.proto
+++ b/protoc_plugin/test/protos/_leading_underscores.proto
@@ -48,6 +48,7 @@
enum _Enum {
_default = 0;
constant = 1;
+ _1digit = 2;
}
service _service {