Răsfoiți Sursa

Remove the usage of attributes for field/method discovery.

Instead, introduce GeneratedCodeInfo which passes in what we need, and adjust the codegen to take account of this.
Jon Skeet 10 ani în urmă
părinte
comite
4668c3dc39
22 a modificat fișierele cu 243 adăugiri și 398 ștergeri
  1. 1 2
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  2. 22 142
      csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs
  3. 13 13
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  4. 12 24
      csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
  5. 66 0
      csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs
  6. 23 19
      csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
  7. 9 18
      csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
  8. 0 58
      csharp/src/Google.Protobuf/Reflection/ProtobufFieldAttribute.cs
  9. 0 52
      csharp/src/Google.Protobuf/Reflection/ProtobufOneofAttribute.cs
  10. 1 20
      csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
  11. 0 5
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  12. 0 1
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  13. 0 1
      src/google/protobuf/compiler/csharp/csharp_map_field.cc
  14. 0 13
      src/google/protobuf/compiler/csharp/csharp_message.cc
  15. 0 2
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  16. 0 2
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  17. 0 1
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  18. 0 1
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  19. 0 1
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
  20. 95 20
      src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
  21. 1 1
      src/google/protobuf/compiler/csharp/csharp_umbrella_class.h
  22. 0 2
      src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc

+ 1 - 2
csharp/src/Google.Protobuf/Google.Protobuf.csproj

@@ -81,6 +81,7 @@
     <Compile Include="Reflection\FieldDescriptor.cs" />
     <Compile Include="Reflection\FieldType.cs" />
     <Compile Include="Reflection\FileDescriptor.cs" />
+    <Compile Include="Reflection\GeneratedCodeInfo.cs" />
     <Compile Include="Reflection\IDescriptor.cs" />
     <Compile Include="Reflection\IFieldAccessor.cs" />
     <Compile Include="Reflection\MapFieldAccessor.cs" />
@@ -90,8 +91,6 @@
     <Compile Include="Reflection\OneofDescriptor.cs" />
     <Compile Include="Reflection\PackageDescriptor.cs" />
     <Compile Include="Reflection\PartialClasses.cs" />
-    <Compile Include="Reflection\ProtobufOneofAttribute.cs" />
-    <Compile Include="Reflection\ProtobufFieldAttribute.cs" />
     <Compile Include="Reflection\ReflectionUtil.cs" />
     <Compile Include="Reflection\RepeatedFieldAccessor.cs" />
     <Compile Include="Reflection\ServiceDescriptor.cs" />

Fișier diff suprimat deoarece este prea mare
+ 22 - 142
csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs


+ 13 - 13
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -46,10 +46,11 @@ namespace Google.Protobuf.Reflection
         private readonly MessageDescriptor containingType;
         private readonly OneofDescriptor containingOneof;
         private FieldType fieldType;
+        private readonly string propertyName; // Annoyingly, needed in Crosslink.
         private IFieldAccessor accessor;
 
         internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
-                                 MessageDescriptor parent, int index)
+                                 MessageDescriptor parent, int index, string propertyName)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
             this.proto = proto;
@@ -76,6 +77,12 @@ namespace Google.Protobuf.Reflection
             }
 
             file.DescriptorPool.AddSymbol(this);
+            // We can't create the accessor until we've cross-linked, unfortunately, as we
+            // may not know whether the type of the field is a map or not. Remember the property name
+            // for later.
+            // We could trust the generated code and check whether the type of the property is
+            // a MapField, but that feels a tad nasty.
+            this.propertyName = propertyName;
         }
 
         /// <summary>
@@ -291,26 +298,19 @@ namespace Google.Protobuf.Reflection
             {
                 throw new DescriptorValidationException(this, "MessageSet format is not supported.");
             }
-
-            accessor = CreateAccessor();
+            accessor = CreateAccessor(propertyName);
         }
 
-        private IFieldAccessor CreateAccessor()
+        private IFieldAccessor CreateAccessor(string propertyName)
         {
-            // TODO: Check the performance of this with some large protos. Each message is O(N^2) in the number of fields,
-            // which isn't great...
-            if (containingType.GeneratedType == null)
+            if (containingType.GeneratedType == null || propertyName == null)
             {
                 return null;
             }
-            var property = containingType
-                .GeneratedType
-                .GetProperties()
-                .FirstOrDefault(p => p.IsDefined(typeof(ProtobufFieldAttribute), false) &&
-                                     p.GetCustomAttributes(typeof(ProtobufFieldAttribute), false).Cast<ProtobufFieldAttribute>().Single().Number == FieldNumber);
+            var property = containingType.GeneratedType.GetProperty(propertyName);
             if (property == null)
             {
-                return null;
+                throw new DescriptorValidationException(this, "Property " + propertyName + " not found in " + containingType.GeneratedType);
             }
             return IsMap ? new MapFieldAccessor(property, this)
                 : IsRepeated ? new RepeatedFieldAccessor(property, this)

+ 12 - 24
csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs

@@ -62,12 +62,11 @@ namespace Google.Protobuf.Reflection
             get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; }
         }
 
-        private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, Type[] generatedTypes)
+        private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo)
         {
             this.pool = pool;
             this.proto = proto;
             this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone());
-            IEnumerator<Type> generatedTypeIterator = generatedTypes == null ? null : ((IEnumerable<Type>)generatedTypes).GetEnumerator();
 
             publicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies);
 
@@ -75,21 +74,15 @@ namespace Google.Protobuf.Reflection
 
             messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType,
                                                                  (message, index) =>
-                                                                 new MessageDescriptor(message, this, null, index, generatedTypeIterator));
+                                                                 new MessageDescriptor(message, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index]));
 
             enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType,
                                                               (enumType, index) =>
-                                                              new EnumDescriptor(enumType, this, null, index, ReflectionUtil.GetNextType(generatedTypeIterator)));
+                                                              new EnumDescriptor(enumType, this, null, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index]));
 
             services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service,
                                                              (service, index) =>
                                                              new ServiceDescriptor(service, this, index));
-
-            // We should now have consumed all the generated types.
-            if (generatedTypeIterator != null && generatedTypeIterator.MoveNext())
-            {
-                throw new ArgumentException("More generated types left over after consuming all expected ones", "generatedTypes");
-            }
         }
 
         /// <summary>
@@ -260,7 +253,7 @@ namespace Google.Protobuf.Reflection
             }
             return null;
         }
-        
+
         /// <summary>
         /// Builds a FileDescriptor from its protocol buffer representation.
         /// </summary>
@@ -269,10 +262,11 @@ namespace Google.Protobuf.Reflection
         /// file's dependencies, in the exact order listed in the .proto file. May be null,
         /// in which case it is treated as an empty array.</param>
         /// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param>
+        /// <param name="generatedCodeInfo">Reflection information, if any. May be null, specifically for non-generated code.</param>
         /// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not
         /// a valid descriptor. This can occur for a number of reasons, such as a field
         /// having an undefined type or because two messages were defined with the same name.</exception>
-        private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, Type[] generatedTypes)
+        private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo)
         {
             // Building descriptors involves two steps: translating and linking.
             // In the translation step (implemented by FileDescriptor's
@@ -289,7 +283,7 @@ namespace Google.Protobuf.Reflection
             }
 
             DescriptorPool pool = new DescriptorPool(dependencies);
-            FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies, generatedTypes);
+            FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies, generatedCodeInfo);
 
             // TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code,
             // and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".)
@@ -330,19 +324,13 @@ namespace Google.Protobuf.Reflection
         /// Creates an instance for generated code.
         /// </summary>
         /// <remarks>
-        /// The <paramref name="generatedTypes"/> parameter should be null for descriptors which don't correspond to
-        /// generated types. Otherwise, the array should represent all the generated types in the file: messages then
-        /// enums. Within each message, there can be nested messages and enums, which must be specified "inline" in the array:
-        /// containing message, nested messages, nested enums - and of course each nested message may contain *more* nested messages,
-        /// etc. All messages within the descriptor should be represented, even if they do not have a generated type - any
-        /// type without a corresponding generated type (such as map entries) should respond to a null element.
-        /// For example, a file with a messages OuterMessage and InnerMessage, and enums OuterEnum and InnerEnum (where
-        /// InnerMessage and InnerEnum are nested within InnerMessage) would result in an array of
-        /// OuterMessage, InnerMessage, InnerEnum, OuterEnum.
+        /// The <paramref name="generatedCodeInfo"/> parameter should be null for descriptors which don't correspond to
+        /// generated types. Otherwise, it should be a <see cref="GeneratedCodeInfo"/> with nested types and nested
+        /// enums corresponding to the types and enums contained within the file descriptor.
         /// </remarks>
         public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
                                                                     FileDescriptor[] dependencies,
-                                                                    Type[] generatedTypes)
+                                                                    GeneratedCodeInfo generatedCodeInfo)
         {
             FileDescriptorProto proto;
             try
@@ -358,7 +346,7 @@ namespace Google.Protobuf.Reflection
             {
                 // When building descriptors for generated code, we allow unknown
                 // dependencies by default.
-                return BuildFrom(proto, dependencies, true, generatedTypes);
+                return BuildFrom(proto, dependencies, true, generatedCodeInfo);
             }
             catch (DescriptorValidationException e)
             {

+ 66 - 0
csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs

@@ -0,0 +1,66 @@
+using System;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Extra information provided by generated code when initializing a message or file descriptor.
+    /// These are constructed as required, and are not long-lived. Hand-written code should
+    /// never need to use this type.
+    /// </summary>
+    public sealed class GeneratedCodeInfo
+    {
+        private static readonly string[] EmptyNames = new string[0];
+        private static readonly GeneratedCodeInfo[] EmptyCodeInfo = new GeneratedCodeInfo[0];
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
+        /// </summary>
+        public Type ClrType { get; private set; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property names (in message descriptor field order)
+        /// for fields in the message for message descriptors.
+        /// </summary>
+        public string[] PropertyNames { get; private set; }
+
+        /// <summary>
+        /// Irrelevant for file descriptors; the CLR property "base" names (in message descriptor oneof order)
+        /// for oneofs in the message for message descriptors. It is expected that for a oneof name of "Foo",
+        /// there will be a "FooCase" property and a "ClearFoo" method.
+        /// </summary>
+        public string[] OneofNames { get; private set; }
+
+        /// <summary>
+        /// The reflection information for types within this file/message descriptor. Elements may be null
+        /// if there is no corresponding generated type, e.g. for map entry types.
+        /// </summary>
+        public GeneratedCodeInfo[] NestedTypes { get; private set; }
+
+        /// <summary>
+        /// The CLR types for enums within this file/message descriptor.
+        /// </summary>
+        public Type[] NestedEnums { get; private set; }
+
+        /// <summary>
+        /// Creates a GeneratedCodeInfo for a message descriptor, with nested types, nested enums, the CLR type, property names and oneof names.
+        /// Each array parameter may be null, to indicate a lack of values.
+        /// The parameter order is designed to make it feasible to format the generated code readably.
+        /// </summary>
+        public GeneratedCodeInfo(Type clrType, string[] propertyNames, string[] oneofNames, Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
+        {
+            NestedTypes = nestedTypes ?? EmptyCodeInfo;
+            NestedEnums = nestedEnums ?? ReflectionUtil.EmptyTypes;
+            ClrType = clrType;
+            PropertyNames = propertyNames ?? EmptyNames;
+            OneofNames = oneofNames ?? EmptyNames;
+        }
+
+        /// <summary>
+        /// Creates a GeneratedCodeInfo for a file descriptor, with only types and enums.
+        /// </summary>
+        public GeneratedCodeInfo(Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes)
+            : this(null, null, null, nestedEnums, nestedTypes)
+        {
+        }
+    }
+}

+ 23 - 19
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs

@@ -66,29 +66,33 @@ namespace Google.Protobuf.Reflection
         private readonly Type generatedType;
         private IDictionary<int, IFieldAccessor> fieldAccessorsByFieldNumber;
         
-        internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, IEnumerator<Type> generatedTypeIterator)
+        internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedCodeInfo generatedCodeInfo)
             : base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
         {
             this.proto = proto;
-            generatedType = ReflectionUtil.GetNextType(generatedTypeIterator);
-            containingType = parent;
-
-            oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl,
-                                                               (oneof, index) =>
-                                                               new OneofDescriptor(oneof, file, this, index));
-
-            nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType,
-                                                                (type, index) =>
-                                                                new MessageDescriptor(type, file, this, index, generatedTypeIterator));
+            generatedType = generatedCodeInfo == null ? null : generatedCodeInfo.ClrType;
 
-            enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType,
-                                                              (type, index) =>
-                                                              new EnumDescriptor(type, file, this, index, ReflectionUtil.GetNextType(generatedTypeIterator)));
+            containingType = parent;
 
-            // TODO(jonskeet): Sort fields first?
-            fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field,
-                                                           (field, index) =>
-                                                           new FieldDescriptor(field, file, this, index));
+            oneofs = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.OneofDecl,
+                (oneof, index) =>
+                new OneofDescriptor(oneof, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.OneofNames[index]));
+
+            nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.NestedType,
+                (type, index) =>
+                new MessageDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedTypes[index]));
+
+            enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.EnumType,
+                (type, index) =>
+                new EnumDescriptor(type, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.NestedEnums[index]));
+
+            fields = DescriptorUtil.ConvertAndMakeReadOnly(
+                proto.Field,
+                (field, index) =>
+                new FieldDescriptor(field, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.PropertyNames[index]));
             file.DescriptorPool.AddSymbol(this);
         }
                 
@@ -220,6 +224,6 @@ namespace Google.Protobuf.Reflection
             }
 
             fieldAccessorsByFieldNumber = new ReadOnlyDictionary<int, IFieldAccessor>(fields.ToDictionary(field => field.FieldNumber, field => field.Accessor));
-        }        
+        }
     }
 }

+ 9 - 18
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs

@@ -41,15 +41,16 @@ namespace Google.Protobuf.Reflection
         private readonly OneofDescriptorProto proto;
         private MessageDescriptor containingType;
         private IList<FieldDescriptor> fields;
-        private OneofAccessor accessor;
+        private readonly OneofAccessor accessor;
 
-        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
+        internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string clrName)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
             this.proto = proto;
             containingType = parent;
 
             file.DescriptorPool.AddSymbol(this);
+            accessor = CreateAccessor(clrName);
         }
 
         /// <summary>
@@ -77,33 +78,23 @@ namespace Google.Protobuf.Reflection
                 }
             }
             fields = new ReadOnlyCollection<FieldDescriptor>(fieldCollection);
-            accessor = CreateAccessor();
         }
 
-        private OneofAccessor CreateAccessor()
+        private OneofAccessor CreateAccessor(string clrName)
         {
-            if (containingType.GeneratedType == null)
+            if (containingType.GeneratedType == null || clrName == null)
             {
                 return null;
             }
-            var caseProperty = containingType
-                .GeneratedType
-                .GetProperties()
-                .FirstOrDefault(p => p.IsDefined(typeof(ProtobufOneofAttribute), false) &&
-                                     p.GetCustomAttributes(typeof(ProtobufOneofAttribute), false).Cast<ProtobufOneofAttribute>().Single().Name == Name);
+            var caseProperty = containingType.GeneratedType.GetProperty(clrName + "Case");
             if (caseProperty == null)
             {
-                return null;
+                throw new DescriptorValidationException(this, "Property " + clrName + "Case not found in " + containingType.GeneratedType);
             }
-
-            var clearMethod = containingType
-                 .GeneratedType
-                 .GetMethods()
-                 .FirstOrDefault(p => p.IsDefined(typeof(ProtobufOneofAttribute), false) &&
-                                      p.GetCustomAttributes(typeof(ProtobufOneofAttribute), false).Cast<ProtobufOneofAttribute>().Single().Name == Name);
+            var clearMethod = containingType.GeneratedType.GetMethod("Clear" + clrName, ReflectionUtil.EmptyTypes);
             if (clearMethod == null)
             {
-                return null;
+                throw new DescriptorValidationException(this, "Method Clear" + clrName + " not found in " + containingType.GeneratedType);
             }
 
             return new OneofAccessor(caseProperty, clearMethod, this);

+ 0 - 58
csharp/src/Google.Protobuf/Reflection/ProtobufFieldAttribute.cs

@@ -1,58 +0,0 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-using System;
-
-namespace Google.Protobuf.Reflection
-{
-    /// <summary>
-    /// Attribute applied to a generated property corresponding to a field in a .proto file.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
-    public sealed class ProtobufFieldAttribute : Attribute
-    {
-        /// <summary>
-        /// The field number in the original .proto file.
-        /// </summary>
-        public int Number { get; set; }
-        
-        /// <summary>
-        /// The field name in the original .proto file.
-        /// </summary>
-        public string Name { get; set; }
-
-        public ProtobufFieldAttribute(int number, string name)
-        {
-            this.Number = number;
-            this.Name = name;
-        }
-    }
-}

+ 0 - 52
csharp/src/Google.Protobuf/Reflection/ProtobufOneofAttribute.cs

@@ -1,52 +0,0 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-using System;
-
-namespace Google.Protobuf.Reflection
-{
-    /// <summary>
-    /// Attribute applied to the "case" property or "clear" method corresponding to a oneof in a .proto file.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)]
-    public sealed class ProtobufOneofAttribute : Attribute
-    {
-        /// <summary>
-        /// The oneof name in the original .proto file.
-        /// </summary>
-        public string Name { get; set; }
-
-        public ProtobufOneofAttribute(string name)
-        {
-            this.Name = name;
-        }
-    }
-}

+ 1 - 20
csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs

@@ -102,25 +102,6 @@ namespace Google.Protobuf.Reflection
             Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType);
             Expression call = Expression.Call(castTarget, method);
             return Expression.Lambda<Action<object>>(call, targetParameter).Compile();
-        }
-
-        /// <summary>
-        /// Returns the next type from an iterator of types, unless the iterator is a null reference,
-        /// in which case null is returned.
-        /// </summary>
-        internal static Type GetNextType(IEnumerator<Type> generatedTypeIterator)
-        {
-            if (generatedTypeIterator == null)
-            {
-                return null;
-            }
-            if (!generatedTypeIterator.MoveNext())
-            {
-                // This parameter name corresponds to any public method supplying the generated types to start with.
-                throw new ArgumentException("More generated types left over after consuming all expected ones", "generatedTypes");
-            }
-            return generatedTypeIterator.Current;
-        }
-
+        }        
     }
 }

+ 0 - 5
src/google/protobuf/compiler/csharp/csharp_field_base.cc

@@ -74,7 +74,6 @@ void FieldGeneratorBase::SetCommonFieldVariables(
 
   (*variables)["property_name"] = property_name();
   (*variables)["type_name"] = type_name();
-  (*variables)["original_name"] = descriptor_->name();
   (*variables)["name"] = name();
   (*variables)["descriptor_name"] = descriptor_->name();
   (*variables)["default_value"] = default_value();
@@ -431,10 +430,6 @@ std::string FieldGeneratorBase::capitalized_type_name() {
   }
 }
 
-std::string FieldGeneratorBase::field_ordinal() {
-  return SimpleItoa(fieldOrdinal_);
-}
-
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -85,7 +85,6 @@ class FieldGeneratorBase : public SourceGeneratorBase {
   std::string default_value(const FieldDescriptor* descriptor);
   std::string number();
   std::string capitalized_type_name();
-  std::string field_ordinal();
 
  private:
   void SetCommonFieldVariables(map<string, string>* variables);

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_map_field.cc

@@ -79,7 +79,6 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");

+ 0 - 13
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -115,19 +115,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
       vars,
       "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
       "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
-  printer->Print(
-    "private static readonly string[] _fieldNames = "
-    "new string[] { $slash$$field_names$$slash$ };\n",
-    "field_names", JoinStrings(field_names(), "\", \""),
-      "slash", field_names().size() > 0 ? "\"" : "");
-  std::vector<std::string> tags;
-  for (int i = 0; i < field_names().size(); i++) {
-    uint32 tag = FixedMakeTag(descriptor_->FindFieldByName(field_names()[i]));
-    tags.push_back(SimpleItoa(tag));
-  }
-  printer->Print(
-    "private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n",
-    "tags", JoinStrings(tags, ", "));
 
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
   if (!descriptor_->containing_type()) {

+ 0 - 2
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -64,7 +64,6 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $name$_; }\n"
     "  set {\n"
@@ -159,7 +158,6 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
     "  set {\n"

+ 0 - 2
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -71,7 +71,6 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $name$_; }\n"
     "  set {\n"
@@ -175,7 +174,6 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
     "  set {\n"

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc

@@ -65,7 +65,6 @@ void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc

@@ -78,7 +78,6 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");

+ 0 - 1
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc

@@ -65,7 +65,6 @@ void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n"
     "  get { return $name$_; }\n"
     "}\n");

+ 95 - 20
src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc

@@ -36,6 +36,7 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
 
 
 #include <google/protobuf/compiler/csharp/csharp_enum.h>
@@ -168,10 +169,10 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
     printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60));
     base64 = base64.substr(60);
   }
-  printer->Outdent();
   printer->Print("\"$base64$\"));\n", "base64", base64);
   printer->Outdent();
   printer->Outdent();
+  printer->Outdent();
 
   // -----------------------------------------------------------------
   // Invoke InternalBuildGeneratedFileFrom() to build the file.
@@ -184,34 +185,108 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
       "full_umbrella_class_name",
       GetFullUmbrellaClassName(file_->dependency(i)));
   }
-  // Specify all the generated types (messages and enums), recursively, as an array. 
   printer->Print("},\n"
-    "    new global::System.Type[] { ");
-  for (int i = 0; i < file_->message_type_count(); i++) {
-    WriteTypeLiterals(file_->message_type(i), printer);
+      "    new pbr::GeneratedCodeInfo(");
+  // Specify all the generated code information, recursively.
+  if (file_->enum_type_count() > 0) {
+      printer->Print("new[] {");
+      for (int i = 0; i < file_->enum_type_count(); i++) {
+          printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+      }
+      printer->Print("}, ");
+  }
+  else {
+      printer->Print("null, ");
+  }
+  if (file_->message_type_count() > 0) {
+      printer->Print("new pbr::GeneratedCodeInfo[] {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (int i = 0; i < file_->message_type_count(); i++) {
+          WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1);
+      }
+      printer->Outdent();
+      printer->Print("\n}));\n");
+      printer->Outdent();
+      printer->Outdent();
   }
-  for (int i = 0; i < file_->enum_type_count(); i++) {
-    printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i)));
+  else {
+      printer->Print("null));\n");
   }
-  printer->Print("});\n");
 
   printer->Outdent();
   printer->Print("}\n");
   printer->Print("#endregion\n\n");
 }
 
-void UmbrellaClassGenerator::WriteTypeLiterals(const Descriptor* descriptor, io::Printer* printer) {
-    if (IsMapEntryMessage(descriptor)) {
-        printer->Print("null, ");
-        return;
-    }
-    printer->Print("typeof($type_name$), ", "type_name", GetClassName(descriptor));
-    for (int i = 0; i < descriptor->nested_type_count(); i++) {
-        WriteTypeLiterals(descriptor->nested_type(i), printer);
-    }
-    for (int i = 0; i < descriptor->enum_type_count(); i++) {
-        printer->Print("typeof($type_name$), ", "type_name", GetClassName(descriptor->enum_type(i)));
-    }
+// Write out the generated code for a particular message. This consists of the CLR type, property names
+// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part
+// can be specified as null if it would be empty, to make the generated code somewhat simpler to read.
+// We write a line break at the end of each generated code info, so that in the final file we'll see all
+// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual,
+// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to
+// read even with multiple levels of nesting.
+// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate
+// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively
+// just controlling the formatting in the generated code.
+void UmbrellaClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) {
+  if (IsMapEntryMessage(descriptor)) {
+    printer->Print("null, ");
+    return;
+  }
+  // Generated message type
+  printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor));
+  
+  // Fields
+  if (descriptor->field_count() > 0) {
+      std::vector<std::string> fields;
+      for (int i = 0; i < descriptor->field_count(); i++) {
+          fields.push_back(GetPropertyName(descriptor->field(i)));
+      }
+      printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Oneofs
+  if (descriptor->oneof_decl_count() > 0) {
+      std::vector<std::string> oneofs;
+      for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
+          oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
+      }
+      printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \""));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested enums
+  if (descriptor->enum_type_count() > 0) {
+      std::vector<std::string> enums;
+      for (int i = 0; i < descriptor->enum_type_count(); i++) {
+          enums.push_back(GetClassName(descriptor->enum_type(i)));
+      }
+      printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof("));
+  }
+  else {
+      printer->Print("null, ");
+  }
+
+  // Nested types
+  if (descriptor->nested_type_count() > 0) {
+      // Need to specify array type explicitly here, as all elements may be null. 
+      printer->Print("new pbr::GeneratedCodeInfo[] { ");
+      for (int i = 0; i < descriptor->nested_type_count(); i++) {
+          WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1);
+      }
+      printer->Print("}");
+  }
+  else {
+      printer->Print("null");
+  }
+  printer->Print(last ? ")" : "),\n");
 }
 
 }  // namespace csharp

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_umbrella_class.h

@@ -57,7 +57,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase {
 
   void WriteIntroduction(io::Printer* printer);
   void WriteDescriptor(io::Printer* printer);
-  void WriteTypeLiterals(const Descriptor* descriptor, io::Printer* printer);
+  void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator);
 };

+ 0 - 2
src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc

@@ -73,7 +73,6 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $name$_; }\n"
     "  set {\n"
@@ -170,7 +169,6 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
   AddDeprecatedFlag(printer);
   printer->Print(
     variables_,
-    "[pbr::ProtobufField($number$, \"$original_name$\")]\n"
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n"
     "  set {\n"

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff