messageMemberNames function
Chooses the GeneratedMessage member names for each field and names associated with each oneof declaration.
Additional names to avoid can be supplied using reserved
.
(This should only be used for mixins.)
Returns MemberNames which holds a list with FieldNames and a list with OneofNames.
Throws DartNameOptionException if a field has this option and it's set to an invalid name.
Implementation
MemberNames messageMemberNames(DescriptorProto descriptor,
String parentClassName, Set<String> usedTopLevelNames,
{Iterable<String> reserved = const []}) {
final fieldList = List<FieldDescriptorProto>.from(descriptor.field);
final sourcePositions =
fieldList.asMap().map((index, field) => MapEntry(field.name, index));
final sorted = fieldList
..sort((FieldDescriptorProto a, FieldDescriptorProto b) {
if (a.number < b.number) return -1;
if (a.number > b.number) return 1;
throw 'multiple fields defined for tag ${a.number} in ${descriptor.name}';
});
// Choose indexes first, based on their position in the sorted list.
final indexes = <String, int>{};
for (final field in sorted) {
final index = indexes.length;
indexes[field.name] = index;
}
final existingNames = <String>{...reservedMemberNames, ...reserved};
final fieldNames = List<FieldNames?>.filled(indexes.length, null);
void takeFieldNames(FieldNames chosen) {
fieldNames[chosen.index!] = chosen;
existingNames.add(chosen.fieldName);
if (chosen.hasMethodName != null) {
existingNames.add(chosen.hasMethodName!);
}
if (chosen.clearMethodName != null) {
existingNames.add(chosen.clearMethodName!);
}
}
// Handle fields with a dart_name option.
// They have higher priority than automatically chosen names.
// Explicitly setting a name that's already taken is a build error.
for (final field in sorted) {
if (_nameOption(field)!.isNotEmpty) {
takeFieldNames(_memberNamesFromOption(descriptor, field,
indexes[field.name]!, sourcePositions[field.name]!, existingNames));
}
}
// Then do other fields.
// They are automatically renamed until we find something unused.
for (final field in sorted) {
if (_nameOption(field)!.isEmpty) {
final index = indexes[field.name]!;
final sourcePosition = sourcePositions[field.name];
takeFieldNames(
_unusedMemberNames(field, index, sourcePosition, existingNames));
}
}
final oneofNames = <OneofNames>[];
void takeOneofNames(OneofNames chosen) {
oneofNames.add(chosen);
existingNames.add(chosen.whichOneofMethodName);
existingNames.add(chosen.clearMethodName);
existingNames.add(chosen.byTagMapName);
}
List<String> oneofNameVariants(String name) {
return [_defaultWhichMethodName(name), _defaultClearMethodName(name)];
}
final realOneofCount = countRealOneofs(descriptor);
for (var i = 0; i < realOneofCount; i++) {
final oneof = descriptor.oneofDecl[i];
final oneofName = disambiguateName(
underscoresToCamelCase(oneof.name), existingNames, defaultSuffixes(),
generateVariants: oneofNameVariants);
final oneofEnumName =
oneofEnumClassName(oneof.name, usedTopLevelNames, parentClassName);
final enumMapName = disambiguateName(
'_${oneofEnumName}ByTag', existingNames, defaultSuffixes());
takeOneofNames(OneofNames(oneof, i, _defaultClearMethodName(oneofName),
_defaultWhichMethodName(oneofName), oneofEnumName, enumMapName));
}
return MemberNames(fieldNames.cast<FieldNames>(), oneofNames);
}