예제 #1
0
        private Dictionary <IDescriptor, DescriptorDeclaration> CreateDeclarationMap()
        {
            var dictionary = new Dictionary <IDescriptor, DescriptorDeclaration>();

            foreach (var location in Proto.SourceCodeInfo?.Location ?? Enumerable.Empty <Location>())
            {
                var descriptor = FindDescriptorForPath(location.Path);
                if (descriptor != null)
                {
                    dictionary[descriptor] = DescriptorDeclaration.FromProto(descriptor, location);
                }
            }
            return(dictionary);
        }
예제 #2
0
        private Dictionary <IDescriptor, DescriptorDeclaration> CreateDeclarationMap()
        {
            var dictionary = new Dictionary <IDescriptor, DescriptorDeclaration>();

            foreach (var location in Proto.SourceCodeInfo?.Location ?? Enumerable.Empty <Location>())
            {
                var descriptor = FindDescriptorForPath(location.Path);
                if (descriptor != null)
                {
                    dictionary[descriptor] = DescriptorDeclaration.FromProto(descriptor, location);
                }
            }
            return(dictionary);

            IDescriptor FindDescriptorForPath(IList <int> path)
            {
                // All complete declarations have an even, non-empty path length
                // (There can be an empty path for a descriptor declaration, but that can't have any comments,
                // so we currently ignore it.)
                if (path.Count == 0 || (path.Count & 1) != 0)
                {
                    return(null);
                }
                IReadOnlyList <DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
                DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);

                for (int i = 2; current != null && i < path.Count; i += 2)
                {
                    var list = current.GetNestedDescriptorListForField(path[i]);
                    current = GetDescriptorFromList(list, path[i + 1]);
                }
                return(current);
            }

            DescriptorBase GetDescriptorFromList(IReadOnlyList <DescriptorBase> list, int index)
            {
                // This is fine: it may be a newer version of protobuf than we understand, with a new descriptor
                // field.
                if (list == null)
                {
                    return(null);
                }
                // We *could* return null to silently continue, but this is basically data corruption.
                if (index < 0 || index >= list.Count)
                {
                    // We don't have much extra information to give at this point unfortunately. If this becomes a problem,
                    // we can pass in the complete path and report that and the file name.
                    throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range");
                }
                return(list[index]);
            }

            IReadOnlyList <DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
            {
                switch (fieldNumber)
                {
                case FileDescriptorProto.ServiceFieldNumber:
                    return((IReadOnlyList <DescriptorBase>)Services);

                case FileDescriptorProto.MessageTypeFieldNumber:
                    return((IReadOnlyList <DescriptorBase>)MessageTypes);

                case FileDescriptorProto.EnumTypeFieldNumber:
                    return((IReadOnlyList <DescriptorBase>)EnumTypes);

                default:
                    return(null);
                }
            }
        }