< Summary

Information
Class: Ice.Internal.Patcher<T>
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/Patcher.cs
Tag: 71_18251537082
Line coverage
77%
Covered lines: 57
Uncovered lines: 17
Coverable lines: 74
Total lines: 136
Line coverage: 77%
Branch coverage
55%
Covered branches: 11
Total branches: 20
Branch coverage: 55%
Method coverage
88%
Covered methods: 8
Total methods: 9
Method coverage: 88.8%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
arrayReadValue<T>(...)100%11100%
listReadValue<T>(...)100%11100%
customSeqReadValue<T>(...)100%11100%
getInvokeInfo<T>(...)58.33%12.021294.44%
.ctor(...)100%11100%
getCount(...)100%1.13150%
invokeAdd(...)100%1.04166.67%
invokeSet(...)100%210%
.cctor()100%11100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/Patcher.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Reflection;
 6
 7namespace Ice.Internal;
 8
 9public sealed class Patcher
 10{
 11    public static System.Action<T?> arrayReadValue<T>(T?[] arr, int index) where
 112        T : Ice.Value => (T? v) => arr[index] = v;
 13
 14    public static System.Action<T?> listReadValue<T>(List<T?> seq, int index) where T : Ice.Value
 15    {
 116        return (T? v) =>
 117        {
 118            int count = seq.Count;
 119            if (index >= count) // Need to grow the sequence.
 120            {
 121                for (int i = count; i < index; i++)
 122                {
 023                    seq.Add(null);
 124                }
 125                seq.Add(v);
 126            }
 127            else
 128            {
 029                seq[index] = v;
 130            }
 031        };
 32    }
 33
 34    public static System.Action<T?> customSeqReadValue<T>(IEnumerable<T?> seq, int index) where T : Ice.Value
 35    {
 136        return (T? v) =>
 137        {
 138            InvokeInfo info = getInvokeInfo<T>(seq.GetType());
 139            int count = info.getCount(seq);
 140            if (index >= count) // Need to grow the sequence.
 141            {
 142                for (int i = count; i < index; i++)
 143                {
 044                    info.invokeAdd(seq, null);
 145                }
 146                info.invokeAdd(seq, v);
 147            }
 148            else
 149            {
 050                info.invokeSet(seq, index, v);
 151            }
 052        };
 53    }
 54
 55    private static InvokeInfo getInvokeInfo<T>(Type t)
 56    {
 157        lock (_methodTable)
 58        {
 159            if (_methodTable.TryGetValue(t, out InvokeInfo? i))
 60            {
 161                return i;
 62            }
 63
 164            MethodInfo? am = t.GetMethod("Add", [typeof(T)]) ??
 165                throw new Ice.MarshalException("Cannot patch a collection without an Add() method");
 166            PropertyInfo? pi = t.GetProperty("Item") ??
 167                throw new Ice.MarshalException("Cannot patch a collection without an indexer");
 168            MethodInfo? sm = pi.GetSetMethod() ??
 169                throw new Ice.MarshalException("Cannot patch a collection without an indexer to set a value");
 170            pi = t.GetProperty("Count");
 171            if (pi == null)
 72            {
 073                throw new Ice.MarshalException("Cannot patch a collection without a Count property");
 74            }
 175            MethodInfo? cm = pi.GetGetMethod() ??
 176                throw new Ice.MarshalException("Cannot patch a collection without a readable Count property");
 177            i = new InvokeInfo(am, sm, cm);
 178            _methodTable.Add(t, i);
 179            return i;
 80        }
 181    }
 82
 83    private class InvokeInfo
 84    {
 185        public InvokeInfo(MethodInfo am, MethodInfo sm, MethodInfo cm)
 86        {
 187            _addMethod = am;
 188            _setMethod = sm;
 189            _countMethod = cm;
 190        }
 91
 92        internal int getCount(System.Collections.IEnumerable seq)
 93        {
 94            try
 95            {
 196                return (int)_countMethod.Invoke(seq, null)!;
 97            }
 098            catch (System.Exception ex)
 99            {
 0100                throw new Ice.MarshalException("Could not read Count property during patching", ex);
 101            }
 1102        }
 103
 104        internal void invokeAdd(System.Collections.IEnumerable seq, object? v)
 105        {
 106            try
 107            {
 1108                object?[] arg = new object?[] { v };
 1109                _addMethod.Invoke(seq, arg);
 1110            }
 0111            catch (System.Exception ex)
 112            {
 0113                throw new Ice.MarshalException("Could not invoke Add method during patching", ex);
 114            }
 1115        }
 116
 117        internal void invokeSet(System.Collections.IEnumerable seq, int index, object? v)
 118        {
 119            try
 120            {
 0121                object?[] args = new object?[] { index, v };
 0122                _setMethod.Invoke(seq, args);
 0123            }
 0124            catch (System.Exception ex)
 125            {
 0126                throw new Ice.MarshalException("Could not call indexer during patching", ex);
 127            }
 0128        }
 129
 130        private readonly MethodInfo _addMethod;
 131        private readonly MethodInfo _setMethod;
 132        private readonly MethodInfo _countMethod;
 133    }
 134
 1135    private static readonly Dictionary<Type, InvokeInfo> _methodTable = new Dictionary<Type, InvokeInfo>();
 136}