Commit 2b61cbf4 authored by Jon Skeet's avatar Jon Skeet

Autogeneration now hopefully close to correct. Library builds! (Not finished though...)

parent de21d2c9
......@@ -43,7 +43,8 @@ Google.ProtocolBuffers.dll_sources = \
Google.ProtocolBuffers.dll: $(Google.ProtocolBuffers.dll_sources)
cp $(srcdir)/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk .
gmcs -codepage:utf8 -debug -target:library -out:Google.ProtocolBuffers.dll $(Google.ProtocolBuffers.dll_sources)
gmcs -codepage:utf8 -debug -target:library -out:Google.ProtocolBuffers.dll \
$(Google.ProtocolBuffers.dll_sources) -keyfile Google.ProtocolBuffers.snk
install-data-local: Google.ProtocolBuffers.dll
gacutil -i Google.ProtocolBuffers.dll -package google
......
......@@ -25,7 +25,6 @@ namespace Google.ProtocolBuffers {
protected abstract IMessage BuildPartialImpl();
protected abstract IBuilder CloneImpl();
protected abstract IMessage DefaultInstanceForTypeImpl { get; }
protected abstract IBuilder CreateBuilderForFieldImpl(FieldDescriptor field);
protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
#endregion
......@@ -47,9 +46,7 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForTypeImpl; }
}
IBuilder IBuilder.CreateBuilderForField(FieldDescriptor field) {
return CreateBuilderForFieldImpl(field);
}
public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
IBuilder IBuilder.ClearField(FieldDescriptor field) {
return ClearFieldImpl(field);
......@@ -67,7 +64,7 @@ namespace Google.ProtocolBuffers {
return this;
}
public IBuilder MergeFrom(IMessage other) {
public virtual IBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
}
......@@ -106,18 +103,18 @@ namespace Google.ProtocolBuffers {
return this;
}
public IBuilder MergeFrom(CodedInputStream input) {
return MergeFrom(input, ExtensionRegistry.Empty);
IBuilder IBuilder.MergeFrom(CodedInputStream input) {
return ((IBuilder)this).MergeFrom(input, ExtensionRegistry.Empty);
}
public IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
UnknownFields = unknownFields.Build();
return this;
}
public IBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
.MergeFrom(unknownFields)
.Build();
......@@ -126,44 +123,44 @@ namespace Google.ProtocolBuffers {
public UnknownFieldSet UnknownFields { get; set; }
public IBuilder MergeFrom(ByteString data) {
IBuilder IBuilder.MergeFrom(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input);
((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input, extensionRegistry);
((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data) {
IBuilder IBuilder.MergeFrom(byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input);
((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input, extensionRegistry);
((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input) {
IBuilder IBuilder.MergeFrom(Stream input) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput);
((IBuilder)this).MergeFrom(codedInput);
codedInput.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput, extensionRegistry);
((IBuilder) this).MergeFrom(codedInput, extensionRegistry);
codedInput.CheckLastTagWas(0);
return this;
}
......
......@@ -13,11 +13,9 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
......@@ -56,7 +54,7 @@ namespace Google.ProtocolBuffers {
}
#endregion
public bool IsInitialized {
public virtual bool IsInitialized {
get {
// Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) {
......@@ -92,7 +90,7 @@ namespace Google.ProtocolBuffers {
return TextFormat.PrintToString(this);
}
public void WriteTo(CodedOutputStream output) {
public virtual void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
......@@ -107,14 +105,14 @@ namespace Google.ProtocolBuffers {
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) {
if (DescriptorForType.Options.MessageSetWireFormat) {
unknownFields.WriteAsMessageSetTo(output);
} else {
unknownFields.WriteTo(output);
}
}
public int SerializedSize {
public virtual int SerializedSize {
get {
int size = memoizedSize;
if (size != -1) {
......@@ -134,7 +132,7 @@ namespace Google.ProtocolBuffers {
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) {
if (DescriptorForType.Options.MessageSetWireFormat) {
size += unknownFields.SerializedSizeAsMessageSet;
} else {
size += unknownFields.SerializedSize;
......@@ -184,73 +182,5 @@ namespace Google.ProtocolBuffers {
hash = (53 * hash) + AllFields.GetHashCode();
return hash;
}
#region IMessage Members
MessageDescriptor IMessage.DescriptorForType {
get { throw new NotImplementedException(); }
}
IDictionary<FieldDescriptor, object> IMessage.AllFields {
get { throw new NotImplementedException(); }
}
bool IMessage.HasField(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field] {
get { throw new NotImplementedException(); }
}
int IMessage.GetRepeatedFieldCount(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field, int index] {
get { throw new NotImplementedException(); }
}
UnknownFieldSet IMessage.UnknownFields {
get { throw new NotImplementedException(); }
}
bool IMessage.IsInitialized {
get { throw new NotImplementedException(); }
}
void IMessage.WriteTo(CodedOutputStream output) {
throw new NotImplementedException();
}
int IMessage.SerializedSize {
get { throw new NotImplementedException(); }
}
bool IMessage.Equals(object other) {
throw new NotImplementedException();
}
int IMessage.GetHashCode() {
throw new NotImplementedException();
}
string IMessage.ToString() {
throw new NotImplementedException();
}
ByteString IMessage.ToByteString() {
throw new NotImplementedException();
}
byte[] IMessage.ToByteArray() {
throw new NotImplementedException();
}
void IMessage.WriteTo(Stream output) {
throw new NotImplementedException();
}
#endregion
}
}
......@@ -5,6 +5,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
/// <summary>
/// This only exists until we've got the real code...
/// </summary>
/*
public abstract class TemporaryMessage<T> : IMessage<T> where T : IMessage<T> {
#region IMessage<T> Members
......@@ -84,7 +85,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public partial class MessageOptions : TemporaryMessage<MessageOptions> {
public bool IsMessageSetWireFormat;
public bool MessageSetWireFormat;
}
public partial class DescriptorProto : TemporaryMessage<DescriptorProto> {
......@@ -123,6 +124,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public string FullName { get; set; }
public FileOptions Options { get; set; }
public string Package { get; set; }
}
public partial class FileOptions : TemporaryMessage<FileOptions> { }
......@@ -143,5 +145,5 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public partial class ServiceOptions : TemporaryMessage<ServiceOptions> { }
public partial class ServiceOptions : TemporaryMessage<ServiceOptions> { } */
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -7,10 +7,6 @@
/// </summary>
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
public interface IDescriptorProto<TOptions> {
/// <summary>
/// The fully qualified name of the descriptor's target.
/// </summary>
string FullName { get; }
/// <summary>
/// The brief name of the descriptor's target.
......
......@@ -32,9 +32,10 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// The fully qualified name of the descriptor's target.
/// TODO(jonskeet): Implement!
/// </summary>
public string FullName {
get { return proto.FullName; }
get { return null; }
}
/// <summary>
......
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Contains lookup tables containing all the descriptors defined in a particular file.
/// </summary>
internal class DescriptorPool {
IDictionary<string, object> byName;
/// <summary>
/// Finds a symbol of the given name within the pool.
/// </summary>
/// <typeparam name="T">The type of symbol to look for</typeparam>
/// <param name="name">Name to look up</param>
/// <returns>The symbol with the given name and type,
/// or null if the symbol doesn't exist or has the wrong type</returns>
internal T FindSymbol<T>(string name) where T : class {
return default(T);
}
}
}
using System;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Allows enum values to express the index within their descriptor.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
internal class EnumDescriptorIndexAttribute : Attribute {
readonly int index;
internal int Index {
get { return index; }
}
internal EnumDescriptorIndexAttribute(int index) {
this.index = index;
}
}
}
using Google.ProtocolBuffers.DescriptorProtos;
using System;
using Google.ProtocolBuffers.DescriptorProtos;
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Descriptors {
public class FileDescriptor : DescriptorBase<FileDescriptorProto, FileOptions> {
private readonly IList<MessageDescriptor> messageTypes;
private readonly IList<EnumDescriptor> enumTypes;
private readonly IList<ServiceDescriptor> services;
private readonly IList<FieldDescriptor> extensions;
private readonly IList<FileDescriptor> dependencies;
private readonly DescriptorPool pool;
public FileDescriptor(FileDescriptorProto proto, FileDescriptor file) : base(proto, file) {
}
/// <summary>
/// The package as declared in the .proto file. This may or may not
/// be equivalent to the .NET namespace of the generated classes.
/// </summary>
public string Package {
get { return Proto.Package; }
}
/// <value>
/// Unmodifiable list of top-level message types declared in this file.
/// </value>
public IList<MessageDescriptor> MessageTypes {
get { return messageTypes; }
}
/// <value>
/// Unmodifiable list of top-level enum types declared in this file.
/// </value>
public IList<EnumDescriptor> EnumTypes {
get { return enumTypes; }
}
/// <value>
/// Unmodifiable list of top-level services declared in this file.
/// </value>
public IList<ServiceDescriptor> Services {
get { return services; }
}
/// <value>
/// Unmodifiable list of top-level extensions declared in this file.
/// </value>
public IList<FieldDescriptor> Extensions {
get { return extensions; }
}
/// <value>
/// Unmodifiable list of this file's dependencies (imports).
/// </value>
public IList<FileDescriptor> Dependencies {
get { return dependencies; }
}
public static FileDescriptor BuildFrom(FileDescriptorProto proto,
FileDescriptor[] dependencies) {
throw new NotImplementedException();
}
/// <summary>
/// This method is to be called by generated code only. It is equivalent
/// to BuilderFrom except that the FileDescriptorProto is encoded in
/// protocol buffer wire format.
/// </summary>
public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
FileDescriptor[] dependencies) {
FileDescriptorProto proto = FileDescriptorProto.ParseFrom(descriptorData);
return BuildFrom(proto, dependencies);
}
}
}
......@@ -16,5 +16,12 @@ namespace Google.ProtocolBuffers.Descriptors {
internal FieldDescriptor FindFieldByNumber(int fieldNumber) {
throw new System.NotImplementedException();
}
/// <value>
/// List of message types nested within this one.
/// </value>
public IList<MessageDescriptor> NestedTypes {
get { throw new System.NotImplementedException(); }
}
}
}
......@@ -136,7 +136,7 @@ namespace Google.ProtocolBuffers {
extension.Descriptor.FieldNumber)] = extension;
FieldDescriptor field = extension.Descriptor;
if (field.ContainingType.Options.IsMessageSetWireFormat
if (field.ContainingType.Options.MessageSetWireFormat
&& field.FieldType == FieldType.Message
&& field.IsOptional
&& field.ExtensionScope == field.MessageType) {
......
......@@ -2,9 +2,7 @@
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
public class FieldAccessorTable<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
public class FieldAccessorTable {
readonly MessageDescriptor descriptor;
......@@ -12,11 +10,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
get { return descriptor; }
}
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseNames) {
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseFieldNames, Type messageType, Type builderType) {
this.descriptor = descriptor;
}
internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] {
internal IFieldAccessor this[FieldDescriptor field] {
get { return null; }
}
}
......
......@@ -5,25 +5,23 @@
/// The property descriptors for each field are created once and then cached.
/// In addition, this interface holds knowledge of repeated fields, builders etc.
/// </summary>
internal interface IFieldAccessor<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
internal interface IFieldAccessor {
/// <summary>
/// Indicates whether the specified message contains the field.
/// </summary>
bool Has(IMessage<TMessage> message);
bool Has(IMessage message);
/// <summary>
/// Gets the count of the repeated field in the specified message.
/// </summary>
int GetRepeatedCount(IMessage<TMessage> message);
int GetRepeatedCount(IMessage message);
/// <summary>
/// Clears the field in the specified builder.
/// </summary>
/// <param name="builder"></param>
void Clear(IBuilder<TMessage> builder);
void Clear(IBuilder builder);
/// <summary>
/// Creates a builder for the type of this field (which must be a message field).
......@@ -33,27 +31,27 @@
/// <summary>
/// Accessor for single fields
/// </summary>
object GetValue(IMessage<TMessage> message);
object GetValue(IMessage message);
/// <summary>
/// Mutator for single fields
/// </summary>
void SetValue(IBuilder<TMessage> builder, object value);
void SetValue(IBuilder builder, object value);
/// <summary>
/// Accessor for repeated fields
/// </summary>
object GetRepeatedValue(IMessage<TMessage> message, int index);
object GetRepeatedValue(IMessage message, int index);
/// <summary>
/// Mutator for repeated fields
/// </summary>
void SetRepeated(IBuilder<TMessage> builder, int index, object value);
void SetRepeated(IBuilder builder, int index, object value);
/// <summary>
/// Adds the specified value to the field in the given builder.
/// </summary>
void AddRepeated(IBuilder<TMessage> builder, object value);
void AddRepeated(IBuilder builder, object value);
/// <summary>
/// Returns a read-only wrapper around the value of a repeated field.
/// </summary>
object GetRepeatedWrapper(IBuilder<TMessage> builder);
object GetRepeatedWrapper(IBuilder builder);
}
}
......@@ -121,7 +121,7 @@ namespace Google.ProtocolBuffers {
uint tag) {
MessageDescriptor type = builder.DescriptorForType;
if (type.Options.IsMessageSetWireFormat
if (type.Options.MessageSetWireFormat
&& tag == WireFormat.MessageSetTag.ItemStart) {
MergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder);
return true;
......@@ -524,7 +524,7 @@ namespace Google.ProtocolBuffers {
/// Writes a single field to a CodedOutputStream.
/// </summary>
public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) {
if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) {
if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value);
} else {
if (field.IsRepeated) {
......@@ -548,7 +548,7 @@ namespace Google.ProtocolBuffers {
FieldDescriptor field = entry.Key;
object value = entry.Value;
if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) {
if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage) value);
} else {
if (field.IsRepeated) {
......
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors;
using System.IO;
namespace Google.ProtocolBuffers {
/// <summary>
......@@ -17,7 +18,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Returns the message being built at the moment.
/// </summary>
protected abstract GeneratedMessage<TMessage,TBuilder> MessageBeingBuilt { get; }
protected abstract TMessage MessageBeingBuilt { get; }
public override bool Initialized {
get { return MessageBeingBuilt.IsInitialized; }
......@@ -40,6 +41,29 @@ namespace Google.ProtocolBuffers {
}
}
/// <summary>
/// Adds all of the specified values to the given collection.
/// </summary>
protected void AddRange<T>(IEnumerable<T> source, IList<T> destination) {
List<T> list = destination as List<T>;
if (list != null) {
list.AddRange(source);
} else {
foreach (T element in source) {
destination.Add(element);
}
}
}
/// <summary>
/// Called by derived classes to parse an unknown field.
/// </summary>
/// <returns>true unless the tag is an end-group tag</returns>
protected bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields,
ExtensionRegistry extensionRegistry, uint tag) {
return unknownFields.MergeFieldFrom(tag, input);
}
public override MessageDescriptor DescriptorForType {
get { return MessageBeingBuilt.DescriptorForType; }
}
......@@ -73,8 +97,8 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForType; }
}
protected override IBuilder CreateBuilderForFieldImpl(FieldDescriptor field) {
return CreateBuilderForField(field);
public override IBuilder CreateBuilderForField(FieldDescriptor field) {
return MessageBeingBuilt.InternalFieldAccessors[field].CreateBuilder();
}
protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
......@@ -85,69 +109,78 @@ namespace Google.ProtocolBuffers {
return AddRepeatedField(field, value);
}
public new abstract IBuilder<TMessage> Clear();
public IBuilder<TMessage> MergeFrom(IMessage<TMessage> other) {
throw new NotImplementedException();
public IBuilder<TMessage> ClearField(FieldDescriptor field) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this);
return this;
}
public abstract TMessage Build();
public abstract TMessage BuildPartial();
public abstract IBuilder<TMessage> Clone();
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input) {
throw new NotImplementedException();
}
// FIXME: Implement!
public virtual IBuilder<TMessage> MergeFrom(TMessage other) { return this; }
public virtual IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) { return this; }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
public IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
MessageBeingBuilt.InternalFieldAccessors[field].AddRepeated(this, value);
return this;
}
public TMessage DefaultInstanceForType {
get { throw new NotImplementedException(); }
public IBuilder<TMessage> MergeFrom(ByteString data) {
((IBuilder) this).MergeFrom(data);
return this;
}
public IBuilder CreateBuilderForField(FieldDescriptor field) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
}
public IBuilder<TMessage> ClearField(FieldDescriptor field) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this);
public IBuilder<TMessage> MergeFrom(byte[] data) {
((IBuilder) this).MergeFrom(data);
return this;
}
public IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
public IBuilder<TMessage> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
}
public new IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(Stream input) {
((IBuilder) this).MergeFrom(input);
return this;
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(input, extensionRegistry);
return this;
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
/// <summary>
/// Like Build(), but will wrap UninitializedMessageException in
/// InvalidProtocolBufferException.
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage BuildParsed() {
if (!Initialized) {
throw new UninitializedMessageException(MessageBeingBuilt).AsInvalidProtocolBufferException();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data) {
throw new NotImplementedException();
return BuildPartial();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
/// <summary>
/// Implementation of <see cref="IBuilder{T}.Build" />.
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage Build() {
if (!Initialized) {
throw new UninitializedMessageException(MessageBeingBuilt);
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input) {
throw new NotImplementedException();
return BuildPartial();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
}
public abstract TMessage BuildPartial();
public abstract IBuilder<TMessage> Clone();
public abstract new IBuilder<TMessage> Clear();
public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input);
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
}
}
......@@ -16,7 +16,7 @@ namespace Google.ProtocolBuffers {
private readonly UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
protected internal abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; }
protected internal abstract FieldAccessorTable InternalFieldAccessors { get; }
public override MessageDescriptor DescriptorForType {
get { return InternalFieldAccessors.Descriptor; }
......@@ -30,13 +30,9 @@ namespace Google.ProtocolBuffers {
return CreateBuilderForType();
}
public IMessage<TMessage> DefaultInstanceForType {
get { throw new NotImplementedException(); }
}
public abstract TMessage DefaultInstanceForType { get; }
public IBuilder<TMessage> CreateBuilderForType() {
throw new NotImplementedException();
}
public abstract IBuilder<TMessage> CreateBuilderForType();
private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
......@@ -44,7 +40,7 @@ namespace Google.ProtocolBuffers {
var ret = new SortedList<FieldDescriptor, object>();
MessageDescriptor descriptor = DescriptorForType;
foreach (FieldDescriptor field in descriptor.Fields) {
IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field];
IFieldAccessor accessor = InternalFieldAccessors[field];
if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0)
|| accessor.Has(this)) {
ret[field] = accessor.GetValue(this);
......
......@@ -125,7 +125,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
IBuilder<T> MergeFrom(IMessage<T> other);
IBuilder<T> MergeFrom(T other);
/// <summary>
/// Constructs the final message. Once this is called, this Builder instance
......@@ -142,7 +142,6 @@ namespace Google.ProtocolBuffers {
/// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned.
/// </summary>
/// <returns></returns>
new T BuildPartial();
/// <summary>
......
......@@ -179,8 +179,7 @@ namespace Google.ProtocolBuffers {
/// method is an abstract method of IMessage whereas DefaultInstance is
/// a static property of a specific class. They return the same thing.
/// </summary>
new IMessage<T> DefaultInstanceForType { get; }
new T DefaultInstanceForType { get; }
#region Builders
/// <summary>
......
......@@ -24,7 +24,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
public class InvalidProtocolBufferException : IOException {
private InvalidProtocolBufferException(string message)
internal InvalidProtocolBufferException(string message)
: base(message) {
}
......
......@@ -13,7 +13,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyKeyFile ("Google.ProtocolBuffers.snk")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
......
......@@ -12,6 +12,8 @@
<AssemblyName>Google.ProtocolBuffers</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
......@@ -45,10 +47,13 @@
<Compile Include="Collections\Lists.cs" />
<Compile Include="Collections\ReadOnlyDictionary.cs" />
<Compile Include="DescriptorProtos\Autogenerated.cs" />
<Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />
<Compile Include="DescriptorProtos\IDescriptorProto.cs" />
<Compile Include="DescriptorProtos\PartialClasses.cs" />
<Compile Include="Descriptors\DescriptorBase.cs" />
<Compile Include="Descriptors\DescriptorPool.cs" />
<Compile Include="Descriptors\EnumDescriptor.cs" />
<Compile Include="Descriptors\EnumDescriptorIndexAttribute.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldMappingAttribute.cs" />
......@@ -77,6 +82,9 @@
<Compile Include="UnknownFieldSet.cs" />
<Compile Include="WireFormat.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\Google.ProtocolBuffers.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
......
......@@ -17,5 +17,12 @@ using System;
namespace Google.ProtocolBuffers {
public class UninitializedMessageException : Exception {
public UninitializedMessageException(IMessage message) {
}
public InvalidProtocolBufferException AsInvalidProtocolBufferException() {
return new InvalidProtocolBufferException(Message);
}
}
}
......@@ -70,7 +70,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
// TODO(jonskeet): Change CONSTANT_CASE into PascalCase
printer->Print(vars,
"[pb::DescriptorIndex($index$)]\r\n"
"[pbd::EnumDescriptorIndex($index$)]\r\n"
"$name$ = $number$,\r\n");
}
printer->Outdent();
......
......@@ -68,20 +68,25 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\r\n"
"private bool has$capitalized_name$;\r\n"
"private $type$ $name$_ = $default$;\r\n"
"public boolean Has$capitalized_name$() { return has$capitalized_name$; }\r\n"
"public $type$ Get$capitalized_name$() { return $name$_; }\r\n");
"public bool Has$capitalized_name$ {\r\n"
" get { return has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ $capitalized_name$ {"
" get { return $name$_; }"
"}\r\n");
}
void EnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"public boolean Has$capitalized_name$() {\r\n"
" return result.Has$capitalized_name$();\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return result.Has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$() {\r\n"
" return result.Get$capitalized_name$();\r\n"
"public $type$ $capitalized_name$ {\r\n"
" get { return result.$capitalized_name$; }\r\n"
" set { Set$capitalized_name$(value); }\r\n"
"}\r\n"
"public Builder Set$capitalized_name$($type$ value) {\r\n"
" result.has$capitalized_name$ = true;\r\n"
......@@ -98,8 +103,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\r\n"
" set$capitalized_name$(other.get$capitalized_name$());\r\n"
"if (other.Has$capitalized_name$) {\r\n"
" $capitalized_name$ = other.$capitalized_name$;\r\n"
"}\r\n");
}
......@@ -111,36 +116,32 @@ GenerateBuildingCode(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"int rawValue = input.readEnum();\r\n"
"$type$ value = $type$.valueOf(rawValue);\r\n"
"if (value == null) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n"
// TODO(jonskeet): Make a more efficient way of doing this
"int rawValue = input.ReadEnum();\r\n"
"if (!global::System.Enum.IsDefined(typeof($type$), rawValue)) {\r\n"
" unknownFields.MergeVarintField($number$, (ulong) rawValue);\r\n"
"} else {\r\n"
" set$capitalized_name$(value);\r\n"
" $capitalized_name$ = ($type$) rawValue;\r\n"
"}\r\n");
}
void EnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" output.writeEnum($number$, get$capitalized_name$().getNumber());\r\n"
"if (Has$capitalized_name$) {\r\n"
" output.WriteEnum($number$, (int) $capitalized_name$);\r\n"
"}\r\n");
}
void EnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
"if (Has$capitalized_name$) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .computeEnumSize($number$, get$capitalized_name$().getNumber());\r\n"
" .ComputeEnumSize($number$, (int) $capitalized_name$);\r\n"
"}\r\n");
}
string EnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
// ===================================================================
RepeatedEnumFieldGenerator::
......@@ -154,17 +155,19 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private System.Collections.Generic.List<$type$> $name$_ =\r\n"
" new System.Collections.Generic.List<$type$> ();\r\n"
"public System.Collections.Generic.List<$type$> $capitalized_name$List() {\r\n"
" return $name$_.AsReadOnly ();\r\n" // note: unmodifiable list
"private scg::IList<$type$> $name$_ = new scg::List<$type$> ();\r\n"
"public scg.IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly($name$_); }\r\n" // note: unmodifiable list
"}\r\n"
// Redundant API calls?
//"public int $capitalized_name$Count() { get { return $name$_.Count; } }\r\n"
//"public $type$ get$capitalized_name$(int index) {\r\n"
//" return $name$_.get(index);\r\n"
//"}\r\n"
// TODO(jonskeet): Possibly. Include for portability to start with though.
"public int $capitalized_name$Count {\r\n"
" get { return $name$_.Count; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return $name$_[index];\r\n"
"}\r\n"
);
}
......@@ -175,36 +178,35 @@ GenerateBuilderMembers(io::Printer* printer) const {
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
"public global::System.Collections.Generic::IList<$type$> get$capitalized_name$List() {\r\n"
" return java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"public global::System.Collections.Generic::IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
"}\r\n"
"public int get$capitalized_name$Count() {\r\n"
" return result.get$capitalized_name$Count();\r\n"
"public int $capitalized_name$Count {\r\n"
" get { return result.get$capitalized_name$Count; } \r\n"
"}\r\n"
"public $type$ get$capitalized_name$(int index) {\r\n"
" return result.get$capitalized_name$(index);\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return result.Get$capitalized_name$(index);\r\n"
"}\r\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_.set(index, value);\r\n"
"public Builder Set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_[index] = value;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.add(value);\r\n"
" result.$name$_.Add(value);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder addAll$capitalized_name$<T>(\r\n"
" global::System.Collections.Generic.IEnumerable<T> values) where T : $type$ {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
"public Builder AddAll$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" super.addAll(values, result.$name$_);\r\n"
" base.AddRange(values, result.$name$_);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder clear$capitalized_name$() {\r\n"
" result.$name$_ = java.util.Collections.emptyList();\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
" return this;\r\n"
"}\r\n");
}
......@@ -212,56 +214,49 @@ GenerateBuilderMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
"if (other.$name$_.Count != 0) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.addAll(other.$name$_);\r\n"
" base.AddRange(other.$name$_, result.$name$_);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\r\n"
" result.$name$_ =\r\n"
" java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"}\r\n");
"result.$name$_ = pbc::Lists.AsReadOnly(result.$name$_);\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"int rawValue = input.readEnum();\r\n"
"int rawValue = input.ReadEnum();\r\n"
"$type$ value = $type$.valueOf(rawValue);\r\n"
"if (value == null) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n"
" unknownFields.MergeVarintField($number$, rawValue);\r\n"
"} else {\r\n"
" add$capitalized_name$(value);\r\n"
" Add$capitalized_name$(value);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n"
" output.writeEnum($number$, element.getNumber());\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.WriteEnum($number$, element.Number);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .computeEnumSize($number$, element.getNumber());\r\n"
" .ComputeEnumSize($number$, element.Number);\r\n"
"}\r\n");
}
string RepeatedEnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -45,8 +45,6 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -40,17 +40,17 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
vars["containing_type"] = ClassName(descriptor_->containing_type());
vars["index"] = SimpleItoa(descriptor_->index());
JavaType csharp_type = GetJavaType(descriptor_);
MappedType mapped_type = GetMappedType(descriptor_);
string singular_type;
switch (csharp_type) {
case JAVATYPE_MESSAGE:
switch (mapped_type) {
case MAPPEDTYPE_MESSAGE:
vars["type"] = ClassName(descriptor_->message_type());
break;
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
vars["type"] = ClassName(descriptor_->enum_type());
break;
default:
vars["type"] = BoxedPrimitiveTypeName(csharp_type);
vars["type"] = MappedTypeName(mapped_type);
break;
}
......
......@@ -51,19 +51,19 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
if (field->is_repeated()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
switch (GetMappedType(field)) {
case MAPPEDTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field);
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field);
default:
return new RepeatedPrimitiveFieldGenerator(field);
}
} else {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
switch (GetMappedType(field)) {
case MAPPEDTYPE_MESSAGE:
return new MessageFieldGenerator(field);
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
return new EnumFieldGenerator(field);
default:
return new PrimitiveFieldGenerator(field);
......
......@@ -50,8 +50,6 @@ class FieldGenerator {
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual string GetBoxedType() const = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
......
......@@ -38,7 +38,7 @@ namespace csharp {
FileGenerator::FileGenerator(const FileDescriptor* file)
: file_(file),
csharp_namespace_(FileJavaPackage(file)),
csharp_namespace_(FileCSharpNamespace(file)),
classname_(FileClassName(file)) {}
FileGenerator::~FileGenerator() {}
......@@ -72,9 +72,9 @@ bool FileGenerator::Validate(string* error) {
": Cannot generate C# output because the file's top-level class name, \"");
error->append(classname_);
error->append(
"\", matches the name of one of the types declared inside it. "
"Please either rename the type or use the csharp_outer_classname "
"option to specify a different outer class name for the .proto file.");
"\", matches the name of one of the message, service or enum types. "
"Please either rename the type or use the csharp_file_classname "
"option to specify a different file-level class name for the .proto file.");
return false;
}
......@@ -88,24 +88,30 @@ void FileGenerator::Generate(io::Printer* printer) {
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n");
// Namespace alias to avoid lines getting horribly long
printer->Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n");
// Namespace aliases to avoid lines getting horribly long
printer->Print("using pb = global::Google.ProtocolBuffers;\r\n");
printer->Print("using pbc = global::Google.ProtocolBuffers.Collections;\r\n");
printer->Print("using pbd = global::Google.ProtocolBuffers.Descriptors;\r\n");
printer->Print("using scg = global::System.Collections.Generic;\r\n");
if (!csharp_namespace_.empty()) {
printer->Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace_);
printer->Print(
"namespace $namespace$ {\r\n"
"\r\n",
"namespace $namespace$ {\r\n",
"namespace", csharp_namespace_);
printer->Indent();
}
printer->Print("\r\n");
printer->Print(
"public sealed class $classname$ {\r\n"
" private $classname$() {}\r\n",
"classname", classname_);
"$access$ static partial class $classname$ {\r\n\r\n",
"classname", classname_,
"access", ClassAccessLevel(file_));
printer->Indent();
// -----------------------------------------------------------------
printer->Print("#region Descriptor\r\n");
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
// and embed it as a byte array, which is parsed and built into real
// descriptors at initialization time.
......@@ -115,10 +121,10 @@ void FileGenerator::Generate(io::Printer* printer) {
file_proto.SerializeToString(&file_data);
printer->Print(
"public static pb::Descriptors.FileDescriptor Descriptor {\r\n"
"public static pbd::FileDescriptor Descriptor {\r\n"
" get { return descriptor; }\r\n"
"}\r\n"
"private static readonly pb::Descriptors.FileDescriptor descriptor = pb::Descriptors.FileDescriptor.InternalBuildGeneratedFileFrom (\r\n"
"private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom (\r\n"
" new byte[] {");
printer->Indent();
printer->Indent();
......@@ -139,7 +145,7 @@ void FileGenerator::Generate(io::Printer* printer) {
}
printer->Outdent();
printer->Outdent();
printer->Print("\r\n}, new pb::Descriptors.FileDescriptor[] {\r\n");
printer->Print("\r\n}, new pbd::FileDescriptor[] {\r\n");
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
" $dependency$.getDescriptor(),\r\n",
......@@ -150,36 +156,58 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Outdent();
printer->Outdent();
printer->Print("\r\n");
printer->Print("#endregion\r\n\r\n");
// -----------------------------------------------------------------
if (!file_->options().csharp_multiple_files()) {
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator(file_->enum_type(i)).Generate(printer);
}
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
for (int i = 0; i < file_->service_count(); i++) {
ServiceGenerator(file_->service(i)).Generate(printer);
}
}
// Extensions must be generated in the outer class since they are values,
// not classes.
printer->Print("#region Extensions\r\n");
for (int i = 0; i < file_->extension_count(); i++) {
ExtensionGenerator(file_->extension(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Static variables\r\n");
// Static variables.
for (int i = 0; i < file_->message_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
}
printer->Print("#endregion\r\n\r\n");
// If we're not nesting classes, the class for the .proto file is done now
if (!file_->options().csharp_nest_classes()) {
printer->Outdent();
printer->Print("}\r\n");
printer->Print("}\r\n\r\n");
}
if (!file_->options().csharp_multiple_files()) {
printer->Print("#region Enums\r\n");
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator(file_->enum_type(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Messages\r\n");
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Services\r\n");
for (int i = 0; i < file_->service_count(); i++) {
ServiceGenerator(file_->service(i)).Generate(printer);
}
printer->Print("#endregion\r\n");
}
// If we were nesting classes, we still need to finish the outer one at some point!
if (file_->options().csharp_nest_classes()) {
printer->Outdent();
printer->Print("}\r\n\r\n");
}
if (!csharp_namespace_.empty()) {
printer->Outdent();
printer->Print("}\r\n");
......@@ -187,12 +215,12 @@ void FileGenerator::Generate(io::Printer* printer) {
}
template<typename GeneratorClass, typename DescriptorClass>
static void GenerateSibling(const string& package_dir,
const string& csharp_namespace,
static void GenerateSibling(const string& csharp_namespace,
const FileDescriptor* file,
const DescriptorClass* descriptor,
OutputDirectory* output_directory,
vector<string>* file_list) {
string filename = package_dir + descriptor->name() + ".cs";
string filename = descriptor->name() + ".cs";
file_list->push_back(filename);
scoped_ptr<io::ZeroCopyOutputStream> output(
......@@ -203,40 +231,62 @@ static void GenerateSibling(const string& package_dir,
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n");
// Namespace alias to avoid lines getting horribly long
printer.Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n");
// Namespace aliases to avoid lines getting horribly long
printer.Print("using pb = global::Google.ProtocolBuffers;\r\n");
printer.Print("using pbc = global::Google.ProtocolBuffers.Collections;\r\n");
printer.Print("using pbd = global::Google.ProtocolBuffers.Descriptors;\r\n");
printer.Print("using scg = global::System.Collections.Generic;\r\n");
if (!csharp_namespace.empty()) {
printer.Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace);
printer.Print(
"namespace $namespace$ {\r\n"
"\r\n",
"namespace $namespace$ {\r\n",
"namespace", csharp_namespace);
printer.Indent();
}
printer.Print("\r\n");
if (file->options().csharp_nest_classes()) {
printer.Print(
"$access$ static partial class $classname$ {\r\n\r\n",
"classname", FileClassName(file),
"access", ClassAccessLevel(file));
printer.Indent();
}
GeneratorClass(descriptor).Generate(&printer);
if (file->options().csharp_nest_classes()) {
printer.Outdent();
printer.Print("}\r\n");
}
if (!csharp_namespace.empty()) {
printer.Outdent();
printer.Print("}\r\n");
}
}
void FileGenerator::GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
void FileGenerator::GenerateSiblings(OutputDirectory* output_directory,
vector<string>* file_list) {
if (file_->options().csharp_multiple_files()) {
for (int i = 0; i < file_->enum_type_count(); i++) {
GenerateSibling<EnumGenerator>(package_dir, csharp_namespace_,
GenerateSibling<EnumGenerator>(csharp_namespace_,
file_,
file_->enum_type(i),
output_directory, file_list);
}
for (int i = 0; i < file_->message_type_count(); i++) {
GenerateSibling<MessageGenerator>(package_dir, csharp_namespace_,
GenerateSibling<MessageGenerator>(csharp_namespace_,
file_,
file_->message_type(i),
output_directory, file_list);
}
for (int i = 0; i < file_->service_count(); i++) {
GenerateSibling<ServiceGenerator>(package_dir, csharp_namespace_,
GenerateSibling<ServiceGenerator>(csharp_namespace_,
file_,
file_->service(i),
output_directory, file_list);
}
......
......@@ -56,8 +56,7 @@ class FileGenerator {
// If we aren't putting everything into one file, this will write all the
// files other than the outer file (i.e. one for each message, enum, and
// service type).
void GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
void GenerateSiblings(OutputDirectory* output_directory,
vector<string>* file_list);
const string& csharp_namespace() { return csharp_namespace_; }
......
......@@ -93,25 +93,20 @@ bool CSharpGenerator::Generate(const FileDescriptor* file,
return false;
}
string package_dir =
StringReplace(file_generator.csharp_namespace(), ".", "/", true);
if (!package_dir.empty()) package_dir += "/";
vector<string> all_files;
string csharp_filename = package_dir;
csharp_filename += file_generator.classname();
string csharp_filename = file_generator.classname();
csharp_filename += ".cs";
all_files.push_back(csharp_filename);
// Generate main csharp file.
// Generate main C# file.
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(csharp_filename));
io::Printer printer(output.get(), '$');
file_generator.Generate(&printer);
// Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
file_generator.GenerateSiblings(output_directory, &all_files);
// Generate output list if requested.
if (!output_list_file.empty()) {
......
......@@ -104,8 +104,8 @@ string StripProto(const string& filename) {
}
string FileClassName(const FileDescriptor* file) {
if (file->options().has_csharp_outer_classname()) {
return file->options().csharp_outer_classname();
if (file->options().has_csharp_file_classname()) {
return file->options().csharp_file_classname();
} else {
string basename;
string::size_type last_slash = file->name().find_last_of('/');
......@@ -118,7 +118,7 @@ string FileClassName(const FileDescriptor* file) {
}
}
string FileJavaPackage(const FileDescriptor* file) {
string FileCSharpNamespace(const FileDescriptor* file) {
if (file->options().has_csharp_namespace()) {
return file->options().csharp_namespace();
} else {
......@@ -131,99 +131,106 @@ string FileJavaPackage(const FileDescriptor* file) {
}
}
string ToJavaName(const string& full_name, const FileDescriptor* file) {
string ToCSharpName(const string& full_name, const FileDescriptor* file) {
string result;
if (file->options().csharp_multiple_files()) {
result = FileJavaPackage(file);
if (!file->options().csharp_nest_classes()) {
result = "";
} else {
result = ClassName(file);
}
if (!result.empty()) {
result += '.';
}
string classname;
if (file->package().empty()) {
result += full_name;
classname = full_name;
} else {
// Strip the proto package from full_name since we've replaced it with
// the Java package.
result += full_name.substr(file->package().size() + 1);
// the C# package.
classname = full_name.substr(file->package().size() + 1);
}
return result;
result += StringReplace(classname, ".", ".Types.", true);
const char *prefix = FileCSharpNamespace(file).empty() ? "global::" : "self::";
return prefix + result;
}
string ClassName(const FileDescriptor* descriptor) {
string result = FileJavaPackage(descriptor);
if (!result.empty()) result += '.';
result += FileClassName(descriptor);
return result;
string alias = FileCSharpNamespace(descriptor).empty() ? "global::" : "self::";
return alias + FileClassName(descriptor);
}
JavaType GetJavaType(FieldDescriptor::Type field_type) {
MappedType GetMappedType(FieldDescriptor::Type field_type) {
switch (field_type) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_SFIXED32:
return JAVATYPE_INT;
return MAPPEDTYPE_INT;
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_SINT64:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_SFIXED64:
return JAVATYPE_LONG;
return MAPPEDTYPE_LONG;
case FieldDescriptor::TYPE_FLOAT:
return JAVATYPE_FLOAT;
return MAPPEDTYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE:
return JAVATYPE_DOUBLE;
return MAPPEDTYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL:
return JAVATYPE_BOOLEAN;
return MAPPEDTYPE_BOOLEAN;
case FieldDescriptor::TYPE_STRING:
return JAVATYPE_STRING;
return MAPPEDTYPE_STRING;
case FieldDescriptor::TYPE_BYTES:
return JAVATYPE_BYTES;
return MAPPEDTYPE_BYTES;
case FieldDescriptor::TYPE_ENUM:
return JAVATYPE_ENUM;
return MAPPEDTYPE_ENUM;
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
return JAVATYPE_MESSAGE;
return MAPPEDTYPE_MESSAGE;
// No default because we want the compiler to complain if any new
// types are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return JAVATYPE_INT;
return MAPPEDTYPE_INT;
}
const char* BoxedPrimitiveTypeName(JavaType type) {
const char* MappedTypeName(MappedType type) {
switch (type) {
case JAVATYPE_INT : return "int";
case JAVATYPE_LONG : return "long";
case JAVATYPE_FLOAT : return "float";
case JAVATYPE_DOUBLE : return "double";
case JAVATYPE_BOOLEAN: return "bool";
case JAVATYPE_STRING : return "string";
case JAVATYPE_BYTES : return "pb::ByteString";
case JAVATYPE_ENUM : return NULL;
case JAVATYPE_MESSAGE: return NULL;
case MAPPEDTYPE_INT : return "int";
case MAPPEDTYPE_LONG : return "long";
case MAPPEDTYPE_UINT : return "uint";
case MAPPEDTYPE_ULONG : return "ulong";
case MAPPEDTYPE_FLOAT : return "float";
case MAPPEDTYPE_DOUBLE : return "double";
case MAPPEDTYPE_BOOLEAN: return "bool";
case MAPPEDTYPE_STRING : return "string";
case MAPPEDTYPE_BYTES : return "pb::ByteString";
case MAPPEDTYPE_ENUM : return NULL;
case MAPPEDTYPE_MESSAGE: return NULL;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
// MappedTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
const char* ClassAccessLevel(const FileDescriptor* file) {
return file->options().csharp_public_classes() ? "public" : "internal";
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -48,52 +48,56 @@ string UnderscoresToCamelCase(const MethodDescriptor* method);
string StripProto(const string& filename);
// Gets the unqualified class name for the file. Each .proto file becomes a
// single Java class, with all its contents nested in that class.
// single C# class, with extra (possibly nested) classes for messages, enums and services.
string FileClassName(const FileDescriptor* file);
// Returns the file's Java package name.
string FileJavaPackage(const FileDescriptor* file);
// Returns the file's C# namespace.
string FileCSharpNamespace(const FileDescriptor* file);
// Converts the given fully-qualified name in the proto namespace to its
// fully-qualified name in the Java namespace, given that it is in the given
// fully-qualified name in the C# namespace, given that it is in the given
// file.
string ToJavaName(const string& full_name, const FileDescriptor* file);
string ToCSharpName(const string& full_name, const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given
// descriptor.
inline string ClassName(const Descriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file());
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
inline string ClassName(const EnumDescriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file());
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
inline string ClassName(const ServiceDescriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file());
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
string ClassName(const FileDescriptor* descriptor);
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
JAVATYPE_FLOAT,
JAVATYPE_DOUBLE,
JAVATYPE_BOOLEAN,
JAVATYPE_STRING,
JAVATYPE_BYTES,
JAVATYPE_ENUM,
JAVATYPE_MESSAGE
enum MappedType {
MAPPEDTYPE_INT,
MAPPEDTYPE_LONG,
MAPPEDTYPE_UINT,
MAPPEDTYPE_ULONG,
MAPPEDTYPE_FLOAT,
MAPPEDTYPE_DOUBLE,
MAPPEDTYPE_BOOLEAN,
MAPPEDTYPE_STRING,
MAPPEDTYPE_BYTES,
MAPPEDTYPE_ENUM,
MAPPEDTYPE_MESSAGE
};
JavaType GetJavaType(FieldDescriptor::Type field_type);
MappedType GetMappedType(FieldDescriptor::Type field_type);
inline JavaType GetJavaType(const FieldDescriptor* field) {
return GetJavaType(field->type());
inline MappedType GetMappedType(const FieldDescriptor* field) {
return GetMappedType(field->type());
}
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
// types.
const char* BoxedPrimitiveTypeName(JavaType type);
// Get the access level for generated classes: public or internal
const char* ClassAccessLevel(const FileDescriptor* file);
// Get the class name for a built-in type (including ByteString).
// Returns NULL for enum and message types.
const char* MappedTypeName(MappedType type);
} // namespace csharp
} // namespace compiler
......
......@@ -144,7 +144,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// used in the construction of descriptors, we have a tricky bootstrapping
// problem. To help control static initialization order, we make sure all
// descriptors and other static data that depends on them are members of
// the outermost class in the file. This way, they will be initialized in
// the proto-descriptor class. This way, they will be initialized in
// a deterministic order.
map<string, string> vars;
......@@ -154,9 +154,9 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
if (descriptor_->containing_type() != NULL) {
vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
}
if (descriptor_->file()->options().csharp_multiple_files()) {
if (!descriptor_->file()->options().csharp_nest_classes()) {
// We can only make these assembly-private since the classes that use them
// are in separate files.
// aren't nested.
vars["private"] = "internal ";
} else {
vars["private"] = "private ";
......@@ -165,23 +165,18 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// The descriptor for this type.
if (descriptor_->containing_type() == NULL) {
printer->Print(vars,
"$private$static readonly pb::Descriptors.Descriptor \r\n"
" internal_$identifier$_descriptor =\r\n"
" getDescriptor().getMessageTypes().get($index$);\r\n");
"$private$static readonly pbd::MessageDescriptor internal__$identifier$__Descriptor \r\n"
" = Descriptor.MessageTypes[$index$];\r\n");
} else {
printer->Print(vars,
"$private$static readonly pb::Descriptors.Descriptor \r\n"
" internal_$identifier$_descriptor =\r\n"
" internal_$parent$_descriptor.getNestedTypes().get($index$);\r\n");
"$private$static readonly pbd::MessageDescriptor internal__$identifier$__Descriptor \r\n"
" = internal__$parent$__Descriptor.NestedTypes[$index$];\r\n");
}
// And the FieldAccessorTable.
printer->Print(vars,
"$private$static\r\n"
" pb::GeneratedMessage.FieldAccessorTable\r\n"
" internal_$identifier$_fieldAccessorTable = new\r\n"
" pb::GeneratedMessage.FieldAccessorTable(\r\n"
" internal_$identifier$_descriptor,\r\n"
"$private$static pb::FieldAccess.FieldAccessorTable internal__$identifier$__FieldAccessorTable\r\n"
" = new pb::FieldAccess.FieldAccessorTable(internal__$identifier$__Descriptor,\r\n"
" new string[] { ");
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print(
......@@ -209,16 +204,18 @@ void MessageGenerator::Generate(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"public sealed class $classname$ : pb::GeneratedMessage.ExtendableMessage<$classname$> {\r\n",
"classname", descriptor_->name());
"$access$ sealed partial class $classname$ : pb::GeneratedMessage.ExtendableMessage<$classname$> {\r\n",
"classname", descriptor_->name(),
"access", ClassAccessLevel(descriptor_->file()));
} else {
printer->Print(
"public sealed class $classname$ : pb::GeneratedMessage {\r\n",
"classname", descriptor_->name());
"$access$ sealed partial class $classname$ : pb::GeneratedMessage<$classname$, $classname$.Builder> {\r\n",
"classname", descriptor_->name(),
"access", ClassAccessLevel(descriptor_->file()));
}
printer->Indent();
printer->Print(
"// Use $classname$.newBuilder() to construct.\r\n"
"// Use $classname$.CreateBuilder() to construct.\r\n"
"private $classname$() {}\r\n"
"\r\n"
"private static readonly $classname$ defaultInstance = new $classname$();\r\n"
......@@ -226,23 +223,29 @@ void MessageGenerator::Generate(io::Printer* printer) {
" get { return defaultInstance; }\r\n"
"}\r\n"
"\r\n"
"public $classname$ DefaultInstanceForType {\r\n"
"public override $classname$ DefaultInstanceForType {\r\n"
" get { return defaultInstance; }\r\n"
"}\r\n"
"\r\n",
"classname", descriptor_->name());
printer->Print(
"public static pb::Descriptors.Descriptor Descriptor {\r\n"
" get { return $fileclass$.internal_$identifier$_descriptor; }\r\n"
"public static pbd::MessageDescriptor Descriptor {\r\n"
" get { return $fileclass$.internal__$identifier$__Descriptor; }\r\n"
"}\r\n"
"\r\n"
"protected pb::GeneratedMessage.FieldAccessorTable InternalGetFieldAccessorTable {\r\n"
" get { return $fileclass$.internal_$identifier$_fieldAccessorTable; }\r\n"
"protected internal override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {\r\n"
" get { return $fileclass$.internal__$identifier$__FieldAccessorTable; }\r\n"
"}\r\n"
"\r\n",
"fileclass", ClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
if (descriptor_->enum_type_count()
+ descriptor_->nested_type_count()
+ descriptor_->extension_count() > 0) {
printer->Print("#region Nested types\r\n");
printer->Print("public static class Types {\r\n");
printer->Indent();
// Nested types and extensions
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
EnumGenerator(descriptor_->enum_type(i)).Generate(printer);
......@@ -255,6 +258,10 @@ void MessageGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < descriptor_->extension_count(); i++) {
ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
}
printer->Outdent();
printer->Print("}\r\n");
printer->Print("#endregion\r\n\r\n");
}
// Fields
for (int i = 0; i < descriptor_->field_count(); i++) {
......@@ -286,12 +293,12 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
sort(sorted_extensions.begin(), sorted_extensions.end(),
ExtensionRangeOrdering());
printer->Print("public void writeTo(pb::CodedOutputStream output) {\r\n");
printer->Print("public override void WriteTo(pb::CodedOutputStream output) {\r\n");
printer->Indent();
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"pb::GeneratedMessage.ExtendableMessage.ExtensionWriter extensionWriter = NewExtensionWriter();\r\n");
"pb::GeneratedMessage.ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter();\r\n");
}
// Merge the fields and the extension ranges, both sorted by field number.
......@@ -322,7 +329,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"}\r\n"
"\r\n"
"private int memoizedSerializedSize = -1;\r\n"
"public int SerializedSize {\r\n");
"public override int SerializedSize {\r\n");
printer->Indent();
printer->Print("get {\r\n");
printer->Indent();
......@@ -345,7 +352,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"size += UnknownFields.SerializedSizeAsMessageSet;\r\n");
} else {
printer->Print(
"size += UnknownFieldsSerializedSize;\r\n");
"size += UnknownFields.SerializedSize;\r\n");
}
printer->Outdent();
......@@ -364,38 +371,38 @@ GenerateParseFromMethods(io::Printer* printer) {
// because they need to be generated even for messages that are optimized
// for code size.
printer->Print(
"public static $classname$ parseFrom(pb::ByteString data) {\r\n"
" return newBuilder().mergeFrom(data).buildParsed();\r\n"
"public static $classname$ ParseFrom(pb::ByteString data) {\r\n"
" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(pb::ByteString data,\r\n"
"public static $classname$ ParseFrom(pb::ByteString data,\r\n"
" pb::ExtensionRegistry extensionRegistry) {\r\n"
" return newBuilder().mergeFrom(data, extensionRegistry)\r\n"
" .buildParsed();\r\n"
" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))\r\n"
" .BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(byte[] data) {\r\n"
" return newBuilder().mergeFrom(data).buildParsed();\r\n"
"public static $classname$ ParseFrom(byte[] data) {\r\n"
" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(byte[] data,\r\n"
" pb::ExtensionRegistry extensionRegistry) {\r\n"
" return newBuilder().mergeFrom(data, extensionRegistry)\r\n"
" .buildParsed();\r\n"
" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry))\r\n"
" .BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(global::System.IO.Stream input) {\r\n"
" return newBuilder().mergeFrom(input).buildParsed();\r\n"
"public static $classname$ ParseFrom(global::System.IO.Stream input) {\r\n"
" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(\r\n"
"public static $classname$ ParseFrom(\r\n"
" global::System.IO.Stream input,\r\n"
" pb::ExtensionRegistry extensionRegistry) {\r\n"
" return newBuilder().mergeFrom(input, extensionRegistry)\r\n"
" .buildParsed();\r\n"
" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry))\r\n"
" .BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(pb::CodedInputStream input) {\r\n"
" return newBuilder().mergeFrom(input).buildParsed();\r\n"
"public static $classname$ ParseFrom(pb::CodedInputStream input) {\r\n"
" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\r\n"
"}\r\n"
"public static $classname$ parseFrom(pb::CodedInputStream input,\r\n"
"public static $classname$ ParseFrom(pb::CodedInputStream input,\r\n"
" pb::ExtensionRegistry extensionRegistry) {\r\n"
" return newBuilder().mergeFrom(input, extensionRegistry)\r\n"
" .buildParsed();\r\n"
" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry))\r\n"
" .BuildParsed();\r\n"
"}\r\n"
"\r\n",
"classname", ClassName(descriptor_));
......@@ -409,7 +416,7 @@ void MessageGenerator::GenerateSerializeOneField(
void MessageGenerator::GenerateSerializeOneExtensionRange(
io::Printer* printer, const Descriptor::ExtensionRange* range) {
printer->Print(
"extensionWriter.writeUntil($end$, output);\r\n",
"extensionWriter.WriteUntil($end$, output);\r\n",
"end", SimpleItoa(range->end));
}
......@@ -417,23 +424,25 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
void MessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
"public static Builder newBuilder() { return new Builder(); }\r\n"
"public Builder newBuilderForType() { return new Builder(); }\r\n"
"public static Builder newBuilder($classname$ prototype) {\r\n"
" return new Builder().mergeFrom(prototype);\r\n"
"public static Builder CreateBuilder() { return new Builder(); }\r\n"
"public override IBuilder<$classname$> CreateBuilderForType() { return new Builder(); }\r\n"
"public static Builder CreateBuilder($classname$ prototype) {\r\n"
" return (Builder) new Builder().MergeFrom(prototype);\r\n"
"}\r\n"
"\r\n",
"classname", ClassName(descriptor_));
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"public sealed class Builder : pb::GeneratedMessage.ExtendableBuilder<\r\n"
"$access$ sealed partial class Builder : pb::GeneratedMessage.ExtendableBuilder<\r\n"
" $classname$, Builder> {\r\n",
"classname", ClassName(descriptor_));
"classname", ClassName(descriptor_),
"access", ClassAccessLevel(descriptor_->file()));
} else {
printer->Print(
"public sealed class Builder : pb::GeneratedMessage.Builder<Builder> {\r\n",
"classname", ClassName(descriptor_));
"$access$ sealed partial class Builder : pb::GeneratedBuilder<$classname$, Builder> {\r\n",
"classname", ClassName(descriptor_),
"access", ClassAccessLevel(descriptor_->file()));
}
printer->Indent();
......@@ -460,31 +469,30 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Print(
"// Construct using $classname$.newBuilder()\r\n"
"private Builder() {}\r\n"
"// Construct using $classname$.CreateBuilder()\r\n"
"internal Builder() {}\r\n"
"\r\n"
"$classname$ result = new $classname$();\r\n"
"\r\n"
"protected $classname$ internalGetResult() {\r\n"
" return result;\r\n"
"protected override $classname$ MessageBeingBuilt {\r\n"
" get { return result; }\r\n"
"}\r\n"
"\r\n"
"public Builder clear() {\r\n"
"public override IBuilder<$classname$> Clear() {\r\n"
" result = new $classname$();\r\n"
" return this;\r\n"
"}\r\n"
"\r\n"
"public Builder clone() {\r\n"
" return new Builder().mergeFrom(result);\r\n"
"public override IBuilder<$classname$> Clone() {\r\n"
" return new Builder().MergeFrom(result);\r\n"
"}\r\n"
"\r\n"
"public pb::Descriptors.Descriptor\r\n"
" getDescriptorForType() {\r\n"
" return $classname$.getDescriptor();\r\n"
"public override pbd::MessageDescriptor DescriptorForType {\r\n"
" get { return $classname$.Descriptor; }\r\n"
"}\r\n"
"\r\n"
"public $classname$ getDefaultInstanceForType() {\r\n"
" return $classname$.getDefaultInstance();\r\n"
"public override $classname$ DefaultInstanceForType {\r\n"
" get { return $classname$.DefaultInstance; }\r\n"
"}\r\n"
"\r\n",
"classname", ClassName(descriptor_));
......@@ -492,23 +500,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
// -----------------------------------------------------------------
printer->Print(
"public $classname$ build() {\r\n"
" if (!isInitialized()) {\r\n"
" throw new pb::UninitializedMessageException(\r\n"
" result);\r\n"
" }\r\n"
" return buildPartial();\r\n"
"}\r\n"
"\r\n"
"private $classname$ buildParsed() {\r\n"
" if (!isInitialized()) {\r\n"
" throw new pb::UninitializedMessageException(\r\n"
" result).asInvalidProtocolBufferException();\r\n"
" }\r\n"
" return buildPartial();\r\n"
"}\r\n"
"\r\n"
"public $classname$ buildPartial() {\r\n",
"public override $classname$ BuildPartial() {\r\n",
"classname", ClassName(descriptor_));
printer->Indent();
......@@ -527,21 +519,22 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
// -----------------------------------------------------------------
//TODO(jonskeet): Work out what this is really for...
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
printer->Print(
"public Builder mergeFrom(pb::Message other) {\r\n"
" if (other instanceof $classname$) {\r\n"
" return mergeFrom(($classname$)other);\r\n"
"public override IBuilder MergeFrom(pb::IMessage other) {\r\n"
" if (other is $classname$) {\r\n"
" return MergeFrom(($classname$) other);\r\n"
" } else {\r\n"
" super.mergeFrom(other);\r\n"
" base.MergeFrom(other);\r\n"
" return this;\r\n"
" }\r\n"
"}\r\n"
"\r\n"
"public Builder mergeFrom($classname$ other) {\r\n"
"public override IBuilder<$classname$> MergeFrom($classname$ other) {\r\n"
// Optimization: If other is the default instance, we know none of its
// fields are set so we can skip the merge.
" if (other == $classname$.getDefaultInstance()) return this;\r\n",
" if (other == $classname$.DefaultInstance) return this;\r\n",
"classname", ClassName(descriptor_));
printer->Indent();
......@@ -551,7 +544,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Outdent();
printer->Print(
" this.mergeUnknownFields(other.getUnknownFields());\r\n"
" this.MergeUnknownFields(other.UnknownFields);\r\n"
" return this;\r\n"
"}\r\n"
"\r\n");
......@@ -565,37 +558,33 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
SortFieldsByNumber(descriptor_));
printer->Print(
"public Builder mergeFrom(\r\n"
" pb::CodedInputStream input) {\r\n"
" return mergeFrom(input,\r\n"
" pb::ExtensionRegistry.getEmptyRegistry());\r\n"
"public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input) {\r\n"
" return MergeFrom(input, pb::ExtensionRegistry.Empty);\r\n"
"}\r\n"
"\r\n"
"public Builder mergeFrom(\r\n"
" pb::CodedInputStream input,\r\n"
" pb::ExtensionRegistry extensionRegistry) {\r\n");
"public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\r\n",
"classname", ClassName(descriptor_));
printer->Indent();
printer->Print(
"pb::UnknownFieldSet.Builder unknownFields =\r\n"
" pb::UnknownFieldSet.newBuilder(\r\n"
" this.getUnknownFields());\r\n"
" pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\r\n"
"while (true) {\r\n");
printer->Indent();
printer->Print(
"int tag = input.readTag();\r\n"
"uint tag = input.ReadTag();\r\n"
"switch (tag) {\r\n");
printer->Indent();
printer->Print(
"case 0:\r\n" // zero signals EOF / limit reached
" this.setUnknownFields(unknownFields.build());\r\n"
" this.UnknownFields = unknownFields.Build();\r\n"
" return this;\r\n"
"default: {\r\n"
" if (!parseUnknownField(input, unknownFields,\r\n"
" if (!ParseUnknownField(input, unknownFields,\r\n"
" extensionRegistry, tag)) {\r\n"
" this.setUnknownFields(unknownFields.build());\r\n"
" this.UnknownFields = unknownFields.Build();\r\n"
" return this;\r\n" // it's an endgroup tag
" }\r\n"
" break;\r\n"
......@@ -632,8 +621,9 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
// ===================================================================
void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
printer->Print(
"public final boolean isInitialized() {\r\n");
printer->Print("public override bool IsInitialized {\r\n");
printer->Indent();
printer->Print("get {\r\n");
printer->Indent();
// Check that all required fields in this message are set.
......@@ -657,22 +647,22 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
switch (field->label()) {
case FieldDescriptor::LABEL_REQUIRED:
printer->Print(
"if (!get$name$().isInitialized()) return false;\r\n",
"if (!$name$.IsInitialized) return false;\r\n",
"type", ClassName(field->message_type()),
"name", UnderscoresToCapitalizedCamelCase(field));
break;
case FieldDescriptor::LABEL_OPTIONAL:
printer->Print(
"if (has$name$()) {\r\n"
" if (!get$name$().isInitialized()) return false;\r\n"
"if (Has$name$) {\r\n"
" if (!$name$.IsInitialized) return false;\r\n"
"}\r\n",
"type", ClassName(field->message_type()),
"name", UnderscoresToCapitalizedCamelCase(field));
break;
case FieldDescriptor::LABEL_REPEATED:
printer->Print(
"for ($type$ element : get$name$List()) {\r\n"
" if (!element.isInitialized()) return false;\r\n"
"foreach ($type$ element in $name$List) {\r\n"
" if (!element.IsInitialized) return false;\r\n"
"}\r\n",
"type", ClassName(field->message_type()),
"name", UnderscoresToCapitalizedCamelCase(field));
......@@ -689,6 +679,9 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
printer->Outdent();
printer->Print(
" return true;\r\n"
"}\r\n");
printer->Outdent();
printer->Print(
"}\r\n"
"\r\n");
}
......
......@@ -65,45 +65,50 @@ MessageFieldGenerator::~MessageFieldGenerator() {}
void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\r\n"
"private $type$ $name$_ = $type$.getDefaultInstance();\r\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\r\n"
"public $type$ get$capitalized_name$() { return $name$_; }\r\n");
"private bool has$capitalized_name$;\r\n"
"private $type$ $name$_ = $type$.DefaultInstance;\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ $capitalized_name$ {\r\n"
" get { return $name$_; }\r\n"
"}\r\n");
}
void MessageFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"public boolean has$capitalized_name$() {\r\n"
" return result.has$capitalized_name$();\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return result.Has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ get$capitalized_name$() {\r\n"
" return result.get$capitalized_name$();\r\n"
"public $type$ $capitalized_name$ {\r\n"
" get { return result.$capitalized_name$; }\r\n"
" set { Set$capitalized_name$(value); }\r\n"
"}\r\n"
"public Builder set$capitalized_name$($type$ value) {\r\n"
"public Builder Set$capitalized_name$($type$ value) {\r\n"
" result.has$capitalized_name$ = true;\r\n"
" result.$name$_ = value;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder set$capitalized_name$($type$.Builder builderForValue) {\r\n"
"public Builder Set$capitalized_name$($type$.Builder builderForValue) {\r\n"
" result.has$capitalized_name$ = true;\r\n"
" result.$name$_ = builderForValue.build();\r\n"
" result.$name$_ = builderForValue.Build();\r\n"
" return this;\r\n"
"}\r\n"
"public Builder merge$capitalized_name$($type$ value) {\r\n"
" if (result.has$capitalized_name$() &&\r\n"
" result.$name$_ != $type$.getDefaultInstance()) {\r\n"
"public Builder Merge$capitalized_name$($type$ value) {\r\n"
" if (result.Has$capitalized_name$ &&\r\n"
" result.$name$_ != $type$.DefaultInstance) {\r\n"
" result.$name$_ =\r\n"
" $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\r\n"
" $type$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\r\n"
" } else {\r\n"
" result.$name$_ = value;\r\n"
" }\r\n"
" result.has$capitalized_name$ = true;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder clear$capitalized_name$() {\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.has$capitalized_name$ = false;\r\n"
" result.$name$_ = $type$.getDefaultInstance();\r\n"
" result.$name$_ = $type$.DefaultInstance;\r\n"
" return this;\r\n"
"}\r\n");
}
......@@ -111,8 +116,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\r\n"
" merge$capitalized_name$(other.get$capitalized_name$());\r\n"
"if (other.Has$capitalized_name$) {\r\n"
" Merge$capitalized_name$(other.$capitalized_name$);\r\n"
"}\r\n");
}
......@@ -124,44 +129,39 @@ GenerateBuildingCode(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = $type$.newBuilder();\r\n"
"if (has$capitalized_name$()) {\r\n"
" subBuilder.mergeFrom(get$capitalized_name$());\r\n"
"$type$.Builder subBuilder = $type$.CreateBuilder();\r\n"
"if (Has$capitalized_name$) {\r\n"
" subBuilder.MergeFrom($capitalized_name$);\r\n"
"}\r\n");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\r\n");
"input.ReadGroup($number$, subBuilder, extensionRegistry);\r\n");
} else {
printer->Print(variables_,
"input.readMessage(subBuilder, extensionRegistry);\r\n");
"input.ReadMessage(subBuilder, extensionRegistry);\r\n");
}
printer->Print(variables_,
"set$capitalized_name$(subBuilder.buildPartial());\r\n");
"$capitalized_name$ = subBuilder.BuildPartial();\r\n");
}
void MessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" output.write$group_or_message$($number$, get$capitalized_name$());\r\n"
"if (Has$capitalized_name$) {\r\n"
" output.Write$group_or_message$($number$, $capitalized_name$);\r\n"
"}\r\n");
}
void MessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .compute$group_or_message$Size($number$, get$capitalized_name$());\r\n"
"if (Has$capitalized_name$) {\r\n"
" size += pb::CodedOutputStream.Compute$group_or_message$Size($number$, $capitalized_name$);\r\n"
"}\r\n");
}
string MessageFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->message_type());
}
// ===================================================================
RepeatedMessageFieldGenerator::
......@@ -175,14 +175,14 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"internal System.Collections.Generic.IList<$type$> Empty$capitalized_name$ =\r\n"
" new System.Collections.ReadOnlyCollection<$type$> ();\r\n"
"internal System.Collections.Generic.IList<$type$> $name$_ = Empty$capitalized_name$;\r\n"
"public System.Collections.Generic.IList<$type$> $capitalized_name$List {\r\n"
"private scg::IList<$type$> $name$_ = pbc::Lists<$type$>.Empty;\r\n"
"public scg::IList<$type$> $capitalized_name$List {\r\n"
" get { return $name$_; } \r\n" // note: unmodifiable list
"}\r\n"
"public int $capitalized_name$Count { get { return $name$_.Count; } }\r\n"
"public $type$ $capitalized_name$(int index) {\r\n"
"public int $capitalized_name$Count\r\n"
" { get { return $name$_.Count; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return $name$_ [index];\r\n"
"}\r\n");
}
......@@ -194,47 +194,46 @@ GenerateBuilderMembers(io::Printer* printer) const {
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
"public System.Collections.Generic.IList<$type$> Get$capitalized_name$List() {\r\n"
" if (result.$name$_ == $type$.Empty$capitalized_name$)\r\n"
" return result.$name$;\r\n"
" return result.$name$_.AsReadOnly ();\r\n"
"public scg::IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
"}\r\n"
"public int Get$capitalized_name$Count() {\r\n"
" return result.Get$capitalized_name$Count();\r\n"
"public int $capitalized_name$Count {\r\n"
" get { return result.$capitalized_name$Count; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return result.Get$capitalized_name$(index);\r\n"
"}\r\n"
"public Builder Set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_ [index] = value;\r\n"
" result.$name$_[index] = value;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder Set$capitalized_name$(int index, "
"$type$.Builder builderForValue) {\r\n"
" result.$name$_ [index] = builderForValue.build();\r\n"
"public Builder Set$capitalized_name$(int index, $type$.Builder builderForValue) {\r\n"
" result.$name$_[index] = builderForValue.Build();\r\n"
" return this;\r\n"
"}\r\n"
"public Builder Add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$ == $type$.Empty$capitalized_name$)\r\n"
" result.$name$ = new System.Collections.Generic.List<$type$>();\r\n"
" if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.Add(value);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder Add$capitalized_name$($type$.Builder builderForValue) {\r\n"
" if (result.$name$ == $type$.Empty$capitalized_name$)\r\n"
" result.$name$ = new System.Collections.Generic.List<$type$>();\r\n"
" result.$name$_.Add(builderForValue.build());\r\n"
" if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.Add(builderForValue.Build());\r\n"
" return this;\r\n"
"}\r\n"
"public Builder AddAll$capitalized_name$<T>(\r\n"
" global::System.Collections.Generic.IEnumerable<T> values) where T : $type$ {\r\n"
" if (result.$name$ == $type$.Empty$capitalized_name$)\r\n"
" result.$name$ = new System.Collections.Generic.List<$type$>();\r\n"
" result.$name$_.AddEnumerable (values);\r\n"
"public Builder AddRange$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
" if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" base.AddRange(values, result.$name$_);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.$name$_ = $type$.Empty$capitalized_name$;\r\n"
" result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
" return this;\r\n"
"}\r\n");
}
......@@ -242,61 +241,55 @@ GenerateBuilderMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_ != $type$.Empty$capitalized_name$) {\r\n"
" if (result.$name$_ == $type$.Empty$capitalized_name$) {\r\n"
" result.$name$_ = new System.Collections.Generic.List<$type$>();\r\n"
"if (other.$name$_.Count != 0) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.AddCollection(other.$name$_);\r\n"
" base.AddRange(other.$name$_, result.$name$_);\r\n"
"}\r\n");
}
void RepeatedMessageFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (result.$name$_ != $type$.Empty$capitalized_name$) {\r\n"
" result.$name$_ =\r\n"
" result.$name$_.AsReadOnly ();\r\n"
"if (result.$name$_ != pbc::Lists<$type$>.Empty) {\r\n"
" result.$name$_ = pbc::Lists<$type$>.AsReadOnly(result.$name$_);\r\n"
"}\r\n");
}
void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = $type$.newBuilder();\r\n");
"$type$.Builder subBuilder = $type$.CreateBuilder();\r\n");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\r\n");
"input.ReadGroup($number$, subBuilder, extensionRegistry);\r\n");
} else {
printer->Print(variables_,
"input.readMessage(subBuilder, extensionRegistry);\r\n");
"input.ReadMessage(subBuilder, extensionRegistry);\r\n");
}
printer->Print(variables_,
"Add$capitalized_name$(subBuilder.buildPartial());\r\n");
"Add$capitalized_name$(subBuilder.BuildPartial());\r\n");
}
void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"foreach ($type$ element in Get$capitalized_name$List()) {\r\n"
" output.write$group_or_message$($number$, element);\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.Write$group_or_message$($number$, element);\r\n"
"}\r\n");
}
void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"foreach ($type$ element in Get$capitalized_name$List()) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .compute$group_or_message$Size($number$, element);\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" size += pb::CodedOutputStream.Compute$group_or_message$Size($number$, element);\r\n"
"}\r\n");
}
string RepeatedMessageFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->message_type());
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -45,8 +45,6 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -36,26 +36,6 @@ namespace csharp {
namespace {
const char* PrimitiveTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT : return "int";
case JAVATYPE_LONG : return "long";
case JAVATYPE_FLOAT : return "float";
case JAVATYPE_DOUBLE : return "double";
case JAVATYPE_BOOLEAN: return "boolean";
case JAVATYPE_STRING : return "string";
case JAVATYPE_BYTES : return "pb::ByteString";
case JAVATYPE_ENUM : return NULL;
case JAVATYPE_MESSAGE: return NULL;
// No default because we want the compiler to complain if any new
// JavaTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
const char* GetCapitalizedType(const FieldDescriptor* field) {
switch (field->type()) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
......@@ -107,7 +87,7 @@ string DefaultValue(const FieldDescriptor* field) {
return SimpleItoa(field->default_value_int64()) + "L";
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(field->default_value_uint64()) +
"L";
"UL";
case FieldDescriptor::CPPTYPE_DOUBLE:
return SimpleDtoa(field->default_value_double()) + "D";
case FieldDescriptor::CPPTYPE_FLOAT:
......@@ -133,8 +113,9 @@ string DefaultValue(const FieldDescriptor* field) {
// Escaping strings correctly for Java and generating efficient
// initializers for ByteStrings are both tricky. We can sidestep the
// whole problem by just grabbing the default value from the descriptor.
// TODO(jonskeet): FIXME!
return strings::Substitute(
"(($0) $1.getDescriptor().getFields().get($2).getDefaultValue())",
"(($0) $1.Descriptor.Fields[$2].DefaultValue)",
isBytes ? "pb::ByteString" : "string",
ClassName(field->containing_type()), field->index());
}
......@@ -159,8 +140,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["capitalized_name"] =
UnderscoresToCapitalizedCamelCase(descriptor);
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
(*variables)["type"] = MappedTypeName(GetMappedType(descriptor));
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
}
......@@ -182,7 +162,7 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private bool has$capitalized_name$;\r\n"
"private $type$ $name$_ = $default$;\r\n"
"public boolean Has$capitalized_name$ {\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ $capitalized_name$ {\r\n"
......@@ -193,18 +173,17 @@ GenerateMembers(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"public boolean Has$capitalized_name$ {\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return result.Has$capitalized_name$; }\r\n"
"}\r\n"
// TODO(jonskeet): Consider whether this is really the right pattern,
// or whether we want a method returning a Builder. This allows for
// object initializers.
"public $type$ $capitalized_name$ {\r\n"
" get { return result.$capitalized_name$; }\r\n"
" set {\r\n"
" set { Set$capitalized_name$(value); }\r\n"
"}\r\n"
"public Builder Set$capitalized_name$($type$ value) {\r\n"
" result.has$capitalized_name$ = true;\r\n"
" result.$name$_ = value;\r\n"
" }\r\n"
" return this;\r\n"
"}\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.has$capitalized_name$ = false;\r\n"
......@@ -216,8 +195,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\r\n"
" set$capitalized_name$(other.get$capitalized_name$());\r\n"
"if (other.Has$capitalized_name$) {\r\n"
" $capitalized_name$ = other.$capitalized_name$;\r\n"
"}\r\n");
}
......@@ -229,30 +208,25 @@ GenerateBuildingCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"set$capitalized_name$(input.read$capitalized_type$());\r\n");
"$capitalized_name$ = input.Read$capitalized_type$();\r\n");
}
void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" output.write$capitalized_type$($number$, get$capitalized_name$());\r\n"
"if (Has$capitalized_name$) {\r\n"
" output.Write$capitalized_type$($number$, $capitalized_name$);\r\n"
"}\r\n");
}
void PrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .compute$capitalized_type$Size($number$, get$capitalized_name$());\r\n"
"if (Has$capitalized_name$) {\r\n"
" size += pb::CodedOutputStream.Compute$capitalized_type$Size($number$, $capitalized_name$);\r\n"
"}\r\n");
}
string PrimitiveFieldGenerator::GetBoxedType() const {
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
}
// ===================================================================
RepeatedPrimitiveFieldGenerator::
......@@ -266,14 +240,15 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private java.util.List<$boxed_type$> $name$_ =\r\n"
" java.util.Collections.emptyList();\r\n"
"public java.util.List<$boxed_type$> get$capitalized_name$List() {\r\n"
" return $name$_;\r\n" // note: unmodifiable list
"private scg::IList<$type$> $name$_ = pbc::Lists<$type$>.Empty;\r\n"
"public scg::IList<$type$> $capitalized_name$List {\r\n"
" get { return $name$_; }\r\n" // note: unmodifiable list
"}\r\n"
"public int get$capitalized_name$Count() { return $name$_.size(); }\r\n"
"public $type$ get$capitalized_name$(int index) {\r\n"
" return $name$_.get(index);\r\n"
"public int $capitalized_name$Count {\r\n" // TODO(jonskeet): Remove?
" get { return $name$_.Count; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n" // TODO(jonskeet): Remove?
" return $name$_[index];\r\n"
"}\r\n");
}
......@@ -284,36 +259,35 @@ GenerateBuilderMembers(io::Printer* printer) const {
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
"public java.util.List<$boxed_type$> get$capitalized_name$List() {\r\n"
" return java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"public scg::IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists<$type$>.AsReadOnly(result.$name$_); }\r\n"
"}\r\n"
"public int get$capitalized_name$Count() {\r\n"
" return result.get$capitalized_name$Count();\r\n"
"public int $capitalized_name$Count {\r\n"
" get { return result.$capitalized_name$Count; }\r\n"
"}\r\n"
"public $type$ get$capitalized_name$(int index) {\r\n"
" return result.get$capitalized_name$(index);\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return result.Get$capitalized_name$(index);\r\n"
"}\r\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_.set(index, value);\r\n"
"public Builder Set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_[index] = value;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\r\n"
"public Builder Add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.add(value);\r\n"
" result.$name$_.Add(value);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder addAll$capitalized_name$(\r\n"
" java.lang.Iterable<? extends $boxed_type$> values) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\r\n"
"public Builder AddRange$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" super.addAll(values, result.$name$_);\r\n"
" base.AddRange(values, result.$name$_);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder clear$capitalized_name$() {\r\n"
" result.$name$_ = java.util.Collections.emptyList();\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
" return this;\r\n"
"}\r\n");
}
......@@ -321,49 +295,43 @@ GenerateBuilderMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$boxed_type$>();\r\n"
"if (other.$name$_.Count != 0) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.addAll(other.$name$_);\r\n"
" base.AddRange(other.$name$_, result.$name$_);\r\n"
"}\r\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\r\n"
" result.$name$_ =\r\n"
" java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"}\r\n");
"result.$name$_ = pbc::Lists<$type$>.AsReadOnly(result.$name$_);\r\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"add$capitalized_name$(input.read$capitalized_type$());\r\n");
"Add$capitalized_name$(input.Read$capitalized_type$());\r\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n"
" output.write$capitalized_type$($number$, element);\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.Write$capitalized_type$($number$, element);\r\n"
"}\r\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .compute$capitalized_type$Size($number$, element);\r\n"
" .Compute$capitalized_type$Size($number$, element);\r\n"
"}\r\n");
}
string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
}
} // namespace csharp
} // namespace compiler
......
......@@ -45,8 +45,6 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......@@ -68,8 +66,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -62,12 +62,12 @@ void ServiceGenerator::Generate(io::Printer* printer) {
printer->Print(
"\r\n"
"public static final\r\n"
" pb::Descriptors.ServiceDescriptor\r\n"
" pbd::ServiceDescriptor\r\n"
" getDescriptor() {\r\n"
" return $file$.getDescriptor().getServices().get($index$);\r\n"
"}\r\n"
"public final pb::Descriptors.ServiceDescriptor\r\n"
" getDescriptorForType() {\r\n"
"public final pbd::ServiceDescriptor\r\n"
" DescriptorForType {\r\n"
" return getDescriptor();\r\n"
"}\r\n",
"file", ClassName(descriptor_->file()),
......@@ -87,14 +87,14 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"\r\n"
"public final void callMethod(\r\n"
" pb::Descriptors.MethodDescriptor method,\r\n"
" pbd::MethodDescriptor method,\r\n"
" pb::RpcController controller,\r\n"
" pb::Message request,\r\n"
" pb::IMessage request,\r\n"
" pb::RpcCallback<\r\n"
" pb::Message> done) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\r\n"
" \"Service.callMethod() given method descriptor for wrong \" +\r\n"
" throw new global::System.ArgumentException(\r\n"
" \"Service.CallMethod() given method descriptor for wrong \" +\r\n"
" \"service type.\");\r\n"
" }\r\n"
" switch(method.getIndex()) {\r\n");
......@@ -118,7 +118,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"default:\r\n"
" throw new java.lang.RuntimeException(\"Can't get here.\");\r\n");
" throw new global::System.InvalidOperationException(\"Can't get here.\");\r\n");
printer->Outdent();
printer->Outdent();
......@@ -133,14 +133,14 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
io::Printer* printer) {
printer->Print(
"public final pb::Message\r\n"
" get$request_or_response$Prototype(\r\n"
" pb::Descriptors.MethodDescriptor method) {\r\n"
" Get$request_or_response$Prototype(\r\n"
" pbd::MethodDescriptor method) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\r\n"
" \"Service.get$request_or_response$Prototype() given method \" +\r\n"
" throw new global::System.ArgumentException(\r\n"
" \"Service.Get$request_or_response$Prototype() given method \" +\r\n"
" \"descriptor for wrong service type.\");\r\n"
" }\r\n"
" switch(method.getIndex()) {\r\n",
" switch(method.Index) {\r\n",
"request_or_response", (which == REQUEST) ? "Request" : "Response");
printer->Indent();
printer->Indent();
......@@ -153,12 +153,12 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
(which == REQUEST) ? method->input_type() : method->output_type());
printer->Print(vars,
"case $index$:\r\n"
" return $type$.getDefaultInstance();\r\n");
" return $type$.DefaultInstance;\r\n");
}
printer->Print(
"default:\r\n"
" throw new java.lang.RuntimeException(\"Can't get here.\");\r\n");
" throw new global::System.ArgumentException(\"Can't get here.\");\r\n");
printer->Outdent();
printer->Outdent();
......@@ -205,14 +205,14 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
" $input$ request,\r\n"
" pb::RpcCallback<$output$> done) {\r\n"
" channel.callMethod(\r\n"
" getDescriptor().getMethods().get($index$),\r\n"
" Descriptor.Methods[$index$],\r\n"
" controller,\r\n"
" request,\r\n"
" $output$.getDefaultInstance(),\r\n"
" $output$.DefaultInstance,\r\n"
" pb::RpcUtil.generalizeCallback(\r\n"
" done,\r\n"
" typeof ($output$),\r\n"
" $output$.getDefaultInstance()));\r\n"
" $output$.DefaultInstance));\r\n"
"}\r\n");
}
......
......@@ -28,8 +28,11 @@ package google.protobuf;
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers";
option csharp_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos";
option csharp_file_classname = "DescriptorProtoFile";
option csharp_multiple_files = false;
option csharp_nest_classes = false;
option csharp_public_classes = true;
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
......@@ -223,10 +226,35 @@ message FileOptions {
optional OptimizeMode optimize_for = 9 [default=CODE_SIZE];
// C# stuff... remove eventually?
// C# stuff... generalise to .NET?
// Sets the namespace where classes generated from this .proto will be
// placed. By default, the proto package is used. Unlike the Java
// generator, the C# generator does *not* create a directory structure
// based on the namespace.
optional string csharp_namespace = 1000;
optional string csharp_outer_classname = 1001;
optional bool csharp_multiple_files = 1002;
// One class is generated to represent the .proto file as a whole.
// It contains the file's descriptor as well as any top-level
// extensions.
optional string csharp_file_classname = 1001;
// If set true, the C# generator will generate a separate .cs file
// for each top-level message, enum and service defined in the .proto
// file. Otherwise, a single .cs file will be generated.
optional bool csharp_multiple_files = 1002 [default=false];
// If set true, the C# generator will use the "whole .proto file" class
// as a container for all the other classes. This value is independent
// of csharp_multiple_files - using partial types, the C# generator
// can still nest classes even when generating multiple files,
// and C# allows multiple public top-level classes in the same
// file.
optional bool csharp_nest_classes = 1003 [default=false];
// If set true, the C# generator will make all its generated classes
// public. If set false, classes will be internal (i.e. only
// visible within the same assembly).
optional bool csharp_public_classes = 1004 [default=true];
}
message MessageOptions {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment