private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                string label = ProtoHelper.FieldLabelToString(opts.Label, false);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                string defaultValue = "";
                if (prop.Options.DefaultValue != null)
                {
                    string formattedValue = ProtoHelper.DefaultValueToString(prop.Options.DefaultValue,
                                                                             prop.ReferencedType);
                    defaultValue = String.Format("[default = {0}]", formattedValue);
                }

                // Proto2 has repeated fields NOT PACKED by default, if they are
                // we mark that explicitly.
                string packed = "";
                if (opts.IsPacked == true && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=true]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0 || defaultValue.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                if (packed.Length > 0)
                {
                    defaultValue = defaultValue.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5}{6};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, defaultValue, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
Example #2
0
        // Get all properties from the type we are analyzing.
        public static List <IRClassProperty> ExtractClassProperties(TypeDefinition _subjectClass,
                                                                    out List <TypeDefinition> references)
        {
            // Will contain all typedefinitions of types referenced by this class.
            references = new List <TypeDefinition>();

            // All properties for the given class definition.
            List <IRClassProperty> properties = new List <IRClassProperty>();

            // Property != field
            // Properties expose fields by providing a getter/setter.
            // The properties are public accessible data, and these are the things that map
            // to protobuffer files.
            foreach (var property in _subjectClass.Properties)
            {
                // Property must have a setter method, otherwise it wouldn't be related to ProtoBuffers schema.
                if (property.SetMethod == null)
                {
                    continue;
                }

                // Object which the current property references.
                TypeDefinition refDefinition;
                // Set of field (proto) options.
                IRClassProperty.ILPropertyOptions options = new IRClassProperty.ILPropertyOptions();
                // Default to invalid field.
                options.Label = FieldLabel.INVALID;
                // IR type of the property.
                PropertyTypeKind propType = InspectorTools.DefaultTypeMapper(property, out refDefinition);

                // IR object - reference placeholder for the IR Class.
                IRTypeNode irReference = null;
                if (propType == PropertyTypeKind.TYPE_REF)
                {
                    irReference = InspectorTools.ConstructIRType(refDefinition);
                    // Also save the reference typedefinition for the caller to process.
                    references.Add(refDefinition);
                }

                // Construct IR property and store.
                var prop = new IRClassProperty
                {
                    Name           = property.Name,
                    Type           = propType,
                    ReferencedType = irReference,
                    Options        = options,
                };
                properties.Add(prop);
            }

            return(properties);
        }
Example #3
0
        private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                // Proto3 syntax has implicit default values!

                string label = ProtoHelper.FieldLabelToString(opts.Label, true);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                // In proto3, the default for a repeated field is PACKED=TRUE.
                // Only if it's not packed.. we set it to false.
                string packed = "";
                if (opts.IsPacked == false && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=false]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
Example #4
0
        // Get all properties from the type we are analyzing.
        public static List <IRClassProperty> ExtractClassProperties(TypeDefinition _subjectClass,
                                                                    out List <TypeDefinition> references)
        {
            // Contains all references (TypeDefinitions) that are referenced by this class.
            references = new List <TypeDefinition>();

            // All properties for the given class.
            List <IRClassProperty> properties = new List <IRClassProperty>();

            // Propertye != field; see SilentOrbitInspector.ExtractClassproperties(..)
            foreach (var property in _subjectClass.Properties)
            {
                // Default to OPTIONAL label. The Google protobuffer compiler is written for
                // proto3 syntax, which does not allow REQUIRED.
                // Everything is implicitly OPTIONAL, but OPTIONAL fields who have the default value
                // will not be written onto the wire.
                // CARE MUST BE TAKEN to provide all necessary values when using these decompiled proto files.
                FieldLabel label = FieldLabel.OPTIONAL;

                // Each schema related property must have a set method, but repeated fields don't have
                // a set method. We must figure out if the property is lib related or schema related!
                if (property.SetMethod == null)
                {
                    // Repeated field have propertyType RepeatedField<X>.
                    if (property.PropertyType.Name.Contains("RepeatedField") == true &&
                        property.PropertyType.IsGenericInstance)
                    {
                        // This field must be analyzed.
                        label = FieldLabel.REPEATED;
                    }
                    else
                    {
                        continue;
                    }
                }

                // Object which the current property references.
                TypeDefinition refDefinition;
                // Field options (directly related to protobuf schema)
                IRClassProperty.ILPropertyOptions opts = new IRClassProperty.ILPropertyOptions();
                // Add label to the property options.
                opts.Label = label;

                // Fetch the IR type of the property. - Doesn't actually matter, the Serialize handler will overwrite this.
                PropertyTypeKind propType = InspectorTools.DefaultTypeMapper(property, out refDefinition);

                // Construct IR reference placeholder.
                IRTypeNode irReference = null;
                if (propType == PropertyTypeKind.TYPE_REF)
                {
                    irReference = InspectorTools.ConstructIRType(refDefinition);
                    // And save the reference TYPEDEFINITION for the caller to process.
                    references.Add(refDefinition);
                }

                // Fetch the fieldNumber for this property.
                var tag = ExtractFieldNumber(_subjectClass, property.Name);
                // Add it to the options.
                opts.PropertyOrder = tag;

                // Construct the IR property and store it.
                var prop = new IRClassProperty()
                {
                    Name           = property.Name,
                    Type           = propType,
                    ReferencedType = irReference,
                    Options        = opts,
                };
                properties.Add(prop);
            }

            return(properties);
        }