Exemplo n.º 1
0
 private CSharpFileOptions BuildOrFakeCSharpOptions()
 {
     // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues
     if (proto.Name == "google/protobuf/descriptor.proto")
     {
         return(new CSharpFileOptions.Builder {
             Namespace = "Google.ProtocolBuffers.DescriptorProtos",
             UmbrellaClassname = "DescriptorProtoFile", NestClasses = false, MultipleFiles = false, PublicClasses = true
         }.Build());
     }
     if (proto.Name == "google/protobuf/csharp_options.proto")
     {
         return(new CSharpFileOptions.Builder {
             Namespace = "Google.ProtocolBuffers.DescriptorProtos",
             UmbrellaClassname = "CSharpOptions", NestClasses = false, MultipleFiles = false, PublicClasses = true
         }.Build());
     }
     CSharpFileOptions.Builder builder = CSharpFileOptions.CreateBuilder();
     if (proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions))
     {
         builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions));
     }
     if (!builder.HasNamespace)
     {
         builder.Namespace = Package;
     }
     if (!builder.HasMultipleFiles)
     {
         builder.MultipleFiles = false;
     }
     if (!builder.HasNestClasses)
     {
         builder.NestClasses = false;
     }
     if (!builder.HasPublicClasses)
     {
         builder.PublicClasses = true;
     }
     if (!builder.HasUmbrellaClassname)
     {
         int    lastSlash = Name.LastIndexOf('/');
         string baseName  = Name.Substring(lastSlash + 1);
         builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName));
     }
     return(builder.Build());
 }
Exemplo n.º 2
0
        /// <summary>
        /// Resolves any dependencies and converts FileDescriptorProtos into FileDescriptors.
        /// The list returned is in the same order as the protos are listed in the descriptor set.
        /// Note: this method is internal rather than private to allow testing.
        /// </summary>
        /// <exception cref="DependencyResolutionException">Not all dependencies could be resolved.</exception>
        public static IList <FileDescriptor> ConvertDescriptors(CSharpFileOptions options,
                                                                params FileDescriptorSet[] descriptorProtos)
        {
            // Simple strategy: Keep going through the list of protos to convert, only doing ones where
            // we've already converted all the dependencies, until we get to a stalemate
            List <FileDescriptorProto> fileList = new List <FileDescriptorProto>();

            foreach (FileDescriptorSet set in descriptorProtos)
            {
                fileList.AddRange(set.FileList);
            }

            FileDescriptor[] converted = new FileDescriptor[fileList.Count];

            Dictionary <string, FileDescriptor> convertedMap = new Dictionary <string, FileDescriptor>();

            int totalConverted = 0;

            bool madeProgress = true;

            while (madeProgress && totalConverted < converted.Length)
            {
                madeProgress = false;
                for (int i = 0; i < converted.Length; i++)
                {
                    if (converted[i] != null)
                    {
                        // Already done this one
                        continue;
                    }
                    FileDescriptorProto candidate    = fileList[i];
                    FileDescriptor[]    dependencies = new FileDescriptor[candidate.DependencyList.Count];


                    CSharpFileOptions.Builder builder = options.ToBuilder();
                    if (candidate.Options.HasExtension(CSharpOptions.CSharpFileOptions))
                    {
                        builder.MergeFrom(
                            candidate.Options.GetExtension(CSharpOptions.CSharpFileOptions));
                    }
                    CSharpFileOptions localOptions = builder.Build();

                    bool foundAllDependencies = true;
                    for (int j = 0; j < dependencies.Length; j++)
                    {
                        if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j]))
                        {
                            // We can auto-magically resolve these since we already have their description
                            // This way if the file is only referencing options it does not need to be built with the
                            // --include_imports definition.
                            if (localOptions.IgnoreGoogleProtobuf &&
                                (candidate.DependencyList[j] == "google/protobuf/csharp_options.proto"))
                            {
                                dependencies[j] = CSharpOptions.Descriptor;
                                continue;
                            }
                            if (localOptions.IgnoreGoogleProtobuf &&
                                (candidate.DependencyList[j] == "google/protobuf/descriptor.proto"))
                            {
                                dependencies[j] = DescriptorProtoFile.Descriptor;
                                continue;
                            }
                            foundAllDependencies = false;
                            break;
                        }
                    }
                    if (!foundAllDependencies)
                    {
                        continue;
                    }
                    madeProgress = true;
                    totalConverted++;
                    converted[i] = FileDescriptor.BuildFrom(candidate, dependencies);
                    convertedMap[candidate.Name] = converted[i];
                }
            }
            if (!madeProgress)
            {
                StringBuilder remaining = new StringBuilder();
                for (int i = 0; i < converted.Length; i++)
                {
                    if (converted[i] == null)
                    {
                        if (remaining.Length != 0)
                        {
                            remaining.Append(", ");
                        }
                        FileDescriptorProto failure = fileList[i];
                        remaining.Append(failure.Name);
                        remaining.Append(":");
                        foreach (string dependency in failure.DependencyList)
                        {
                            if (!convertedMap.ContainsKey(dependency))
                            {
                                remaining.Append(" ");
                                remaining.Append(dependency);
                            }
                        }
                        remaining.Append(";");
                    }
                }
                throw new DependencyResolutionException("Unable to resolve all dependencies: " + remaining);
            }
            return(Lists.AsReadOnly(converted));
        }
        private CSharpFileOptions BuildOrFakeWithDefaultOptions(CSharpFileOptions defaultOptions)
        {
            // Fix for being able to relocate these files to any directory structure
            if (proto.Package == "google.protobuf")
            {
                string filename = Path.GetFileName(proto.Name);
                // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues)
                if (filename == "descriptor.proto")
                {
                    return(new CSharpFileOptions.Builder {
                        Namespace = "Google.ProtocolBuffers.DescriptorProtos",
                        UmbrellaClassname = "DescriptorProtoFile",
                        NestClasses = false,
                        MultipleFiles = false,
                        PublicClasses = true,
                        OutputDirectory = defaultOptions.OutputDirectory,
                        IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf
                    }.Build());
                }
                if (filename == "csharp_options.proto")
                {
                    return(new CSharpFileOptions.Builder {
                        Namespace = "Google.ProtocolBuffers.DescriptorProtos",
                        UmbrellaClassname = "CSharpOptions",
                        NestClasses = false,
                        MultipleFiles = false,
                        PublicClasses = true,
                        OutputDirectory = defaultOptions.OutputDirectory,
                        IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf
                    }.Build());
                }
            }
            CSharpFileOptions.Builder builder = defaultOptions.ToBuilder();
            if (proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions))
            {
                builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions));
            }
            if (!builder.HasNamespace)
            {
                builder.Namespace = Package;
            }
            if (!builder.HasUmbrellaClassname)
            {
                int    lastSlash = Name.LastIndexOf('/');
                string baseName  = Name.Substring(lastSlash + 1);
                builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName));
            }

            // Auto-fix for name collision by placing umbrella class into a new namespace.  This
            // still won't fix the collisions with nesting enabled; however, you have to turn that on explicitly anyway.
            if (!builder.NestClasses && !builder.HasUmbrellaNamespace)
            {
                bool collision = false;
                foreach (IDescriptor d in MessageTypes)
                {
                    collision |= d.Name == builder.UmbrellaClassname;
                }
                foreach (IDescriptor d in Services)
                {
                    collision |= d.Name == builder.UmbrellaClassname;
                }
                foreach (IDescriptor d in EnumTypes)
                {
                    collision |= d.Name == builder.UmbrellaClassname;
                }
                if (collision)
                {
                    builder.UmbrellaNamespace = "Proto";
                }
            }

            return(builder.Build());
        }
        private void ParseArguments(IList <string> tmpReasons)
        {
            bool doHelp = Arguments.Count == 0;

            InputFiles = new List <string>();
            CSharpFileOptions.Builder            builder = FileOptions.ToBuilder();
            Dictionary <string, FieldDescriptor> fields  =
                new Dictionary <string, FieldDescriptor>(StringComparer.OrdinalIgnoreCase);

            foreach (FieldDescriptor fld in builder.DescriptorForType.Fields)
            {
                fields.Add(fld.Name, fld);
            }

            foreach (string argument in Arguments)
            {
                if (StringComparer.OrdinalIgnoreCase.Equals("-help", argument) ||
                    StringComparer.OrdinalIgnoreCase.Equals("/help", argument) ||
                    StringComparer.OrdinalIgnoreCase.Equals("-?", argument) ||
                    StringComparer.OrdinalIgnoreCase.Equals("/?", argument))
                {
                    doHelp = true;
                    break;
                }

                Match m = ArgMatch.Match(argument);
                if (m.Success)
                {
                    FieldDescriptor fld;
                    string          name  = m.Groups["name"].Value;
                    string          value = m.Groups["value"].Value;

                    if (fields.TryGetValue(name, out fld))
                    {
                        object obj;
                        if (TryCoerceType(value, fld, out obj, tmpReasons))
                        {
                            builder[fld] = obj;
                        }
                    }
                    else if (name == "line_break")
                    {
                        string tmp;
                        if (LineBreaks.TryGetValue(value, out tmp))
                        {
                            LineBreak = tmp;
                        }
                        else
                        {
                            tmpReasons.Add("Invalid value for 'line_break': " + value + ".");
                        }
                    }
                    else if (!File.Exists(argument))
                    {
                        doHelp = true;
                        tmpReasons.Add("Unknown argument '" + name + "'.");
                    }
                    else
                    {
                        InputFiles.Add(argument);
                    }
                }
                else
                {
                    InputFiles.Add(argument);
                }
            }

            if (doHelp || InputFiles.Count == 0)
            {
                tmpReasons.Add("Arguments:");
                foreach (KeyValuePair <string, FieldDescriptor> field in fields)
                {
                    tmpReasons.Add(String.Format("-{0}=[{1}]", field.Key, field.Value.FieldType));
                }
                tmpReasons.Add("-line_break=[" + string.Join("|", new List <string>(LineBreaks.Keys).ToArray()) + "]");
                tmpReasons.Add("followed by one or more file paths.");
            }
            else
            {
                FileOptions = builder.Build();
            }
        }