blob: 8bd3022715f7d3afbb80d3c8df18cc1cfd70bcac [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of protoc;
class EnumAlias {
final EnumValueDescriptorProto value;
final EnumValueDescriptorProto canonicalValue;
EnumAlias(this.value, this.canonicalValue);
}
class EnumGenerator extends ProtobufContainer {
final ProtobufContainer _parent;
final String classname;
final String fullName;
final EnumDescriptorProto _descriptor;
final List<EnumValueDescriptorProto> _canonicalValues =
<EnumValueDescriptorProto>[];
final List<EnumAlias> _aliases = <EnumAlias>[];
EnumGenerator(EnumDescriptorProto descriptor, ProtobufContainer parent)
: assert(parent != null),
_parent = parent,
classname = messageOrEnumClassName(descriptor.name,
parent: parent?.classname ?? ''),
fullName = parent.fullName == ''
? descriptor.name
: '${parent.fullName}.${descriptor.name}',
_descriptor = descriptor {
for (EnumValueDescriptorProto value in descriptor.value) {
EnumValueDescriptorProto canonicalValue =
descriptor.value.firstWhere((v) => v.number == value.number);
if (value == canonicalValue) {
_canonicalValues.add(value);
} else {
_aliases.add(new EnumAlias(value, canonicalValue));
}
}
}
String get package => _parent.package;
FileGenerator get fileGen => _parent.fileGen;
/// Make this enum available as a field type.
void register(GenerationContext ctx) {
ctx.registerFieldType(this);
}
/// Returns a const expression that evaluates to the JSON for this message.
/// [usage] represents the .pb.dart file where the expression will be used.
String getJsonConstant(FileGenerator usage) {
var name = "$classname\$json";
if (usage.protoFileUri == fileGen.protoFileUri) {
return name;
}
return "$fileImportPrefix.$name";
}
void generate(IndentingWriter out) {
out.addBlock(
'class ${classname} extends $_protobufImportPrefix.ProtobufEnum {',
'}\n', () {
// -----------------------------------------------------------------
// Define enum types.
var reservedNames = reservedEnumNames;
for (EnumValueDescriptorProto val in _canonicalValues) {
final name = unusedEnumNames(val.name, reservedNames);
out.println('static const ${classname} $name = '
"const ${classname}._(${val.number}, '$name');");
}
if (!_aliases.isEmpty) {
out.println();
for (EnumAlias alias in _aliases) {
final name = unusedEnumNames(alias.value.name, reservedNames);
out.println('static const ${classname} $name ='
' ${alias.canonicalValue.name};');
}
}
out.println();
out.println('static const List<${classname}> values ='
' const <${classname}> [');
reservedNames = reservedEnumNames;
for (EnumValueDescriptorProto val in _canonicalValues) {
final name = unusedEnumNames(val.name, reservedNames);
out.println(' $name,');
}
out.println('];');
out.println();
out.println('static final Map<int, dynamic> _byValue ='
' $_protobufImportPrefix.ProtobufEnum.initByValue(values);');
out.println('static ${classname} valueOf(int value) =>'
' _byValue[value] as ${classname};');
out.addBlock('static void $checkItem($classname v) {', '}', () {
out.println('if (v is! $classname)'
" $_protobufImportPrefix.checkItemFailed(v, '$classname');");
});
out.println();
out.println('const ${classname}._(int v, String n) '
': super(v, n);');
});
}
/// Writes a Dart constant containing the JSON for the EnumProtoDescriptor.
void generateConstants(IndentingWriter out) {
var name = getJsonConstant(fileGen);
var json = _descriptor.writeToJsonMap();
out.print("const $name = ");
writeJsonConst(out, json);
out.println(";");
out.println();
}
}