blob: aca8255e79c186ed4c771598a64ed8e0e6d1a12c [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 ExtensionGenerator {
final FieldDescriptorProto _descriptor;
final ProtobufContainer _parent;
// populated by resolve()
ProtobufField _field;
final String _extensionName;
String _extendedFullName = "";
ExtensionGenerator(this._descriptor, this._parent, Set<String> usedNames)
: _extensionName = extensionName(_descriptor, usedNames);
void resolve(GenerationContext ctx) {
_field = new ProtobufField.extension(_descriptor, _parent, ctx);
ProtobufContainer extendedType = ctx.getFieldType(_descriptor.extendee);
// TODO(skybrian) When would this be null?
if (extendedType != null) {
_extendedFullName = extendedType.fullName;
}
}
String get package => _parent.package;
/// The generator of the .pb.dart file where this extension will be defined.
FileGenerator get fileGen => _parent.fileGen;
String get name {
if (_field == null) throw new StateError("resolve not called");
String name = _extensionName;
return _parent is MessageGenerator ? '${_parent.classname}.$name' : name;
}
bool get needsFixnumImport {
if (_field == null) throw new StateError("resolve not called");
return _field.needsFixnumImport;
}
/// Adds dependencies of [generate] to [imports].
///
/// For each .pb.dart file that the generated code needs to import,
/// add its generator.
void addImportsTo(
Set<FileGenerator> imports, Set<FileGenerator> enumImports) {
if (_field == null) throw new StateError("resolve not called");
var typeGen = _field.baseType.generator;
if (typeGen != null) {
// The type of this extension is defined in a different file,
// so we need to import it.
if (typeGen is EnumGenerator) {
// Enums are always in a different file.
enumImports.add(typeGen.fileGen);
} else if (typeGen.fileGen != fileGen) {
imports.add(typeGen.fileGen);
}
}
}
/// Adds dependencies of [generateConstants] to [imports].
///
/// For each .pb.dart file that the generated code needs to import,
/// add its generator.
void addConstantImportsTo(Set<FileGenerator> imports) {
if (_field == null) throw new StateError("resolve not called");
// No dependencies - nothing to do.
}
void generate(IndentingWriter out) {
if (_field == null) throw new StateError("resolve not called");
String name = _extensionName;
var type = _field.baseType;
var dartType = type.getDartType(fileGen);
if (_field.isRepeated) {
out.print('static final $_protobufImportPrefix.Extension $name = '
'new $_protobufImportPrefix.Extension<$dartType>.repeated(\'$_extendedFullName\','
' \'$name\', ${_field.number}, ${_field.typeConstant}');
if (type.isMessage || type.isGroup) {
out.println(', $dartType.$checkItem, $dartType.create);');
} else if (type.isEnum) {
out.println(', $dartType.$checkItem, null, '
'$dartType.valueOf, $dartType.values);');
} else {
out.println(
", $_protobufImportPrefix.getCheckFunction(${_field.typeConstant}));");
}
return;
}
out.print('static final $_protobufImportPrefix.Extension $name = '
'new $_protobufImportPrefix.Extension<$dartType>(\'$_extendedFullName\', \'$name\', '
'${_field.number}, ${_field.typeConstant}');
String initializer = _field.generateDefaultFunction(fileGen);
if (type.isMessage || type.isGroup) {
out.println(', $initializer, $dartType.create);');
} else if (type.isEnum) {
var dartEnum = type.getDartType(fileGen);
String enumParams = '(var v) => $dartEnum.valueOf(v), $dartEnum.values';
out.println(", $initializer, null, $enumParams);");
} else if (initializer != null) {
out.println(", $initializer);");
} else {
out.println(");");
}
}
}