Пример #1
0
 internal VTableSlot(TypeSig defDeclType, MethodDef def, TypeSig decl, VTableSignature signature,
                     VTableSlot overrides)
 {
     MethodDefDeclType = defDeclType;
     MethodDef         = def;
     DeclaringType     = decl;
     Signature         = signature;
     Parent            = overrides;
 }
Пример #2
0
 internal VTableSlot(MethodDef def, TypeSig decl, VTableSignature signature)
     : this(def.DeclaringType.ToTypeSig(), def, decl, signature, null)
 {
 }
Пример #3
0
            public VTable Build()
            {
                // Inherits base type's slots
                var baseVTbl = (VTable)_storage.GetVTable(_typeDef.GetBaseTypeThrow());

                if (baseVTbl != null)
                {
                    Inherits(baseVTbl);
                }

                var virtualMethods = _typeDef.Methods
                                     .Where(method => method.IsVirtual)
                                     .ToDictionary(
                    VTableSignature.FromMethod,
                    method => method
                    );

                if (_typeDef.FullName.Contains("SubjectBase"))
                {
                }

                // Explicit interface implementation
                foreach (var iface in _typeDef.Interfaces)
                {
                    var ifaceVTbl = (VTable)_storage.GetVTable(iface.Interface);
                    if (ifaceVTbl != null)
                    {
                        Implements(virtualMethods, ifaceVTbl, iface.Interface.ToTypeSig());
                    }
                }

                // Normal interface implementation
                if (!_typeDef.IsInterface)
                {
                    // Interface methods cannot implements base interface methods.
                    foreach (var iface in _interfaceSlots.Values)
                    {
                        foreach (var entry in iface.ToList())
                        {
                            if (!entry.Value.MethodDef.DeclaringType.IsInterface)
                            {
                                continue;
                            }
                            // This is the step 1 of 12.2 algorithm -- find implementation for still empty slots.
                            // Note that it seems we should include newslot methods as well, despite what the standard said.
                            if (virtualMethods.TryGetValue(entry.Key, out var impl))
                            {
                                iface[entry.Key] = OverridenBy(entry.Value, impl);
                            }
                            else if (_slotsMap.TryGetValue(entry.Key, out var implSlot))
                            {
                                iface[entry.Key] = OverridenBy(entry.Value, implSlot.MethodDef);
                            }
                        }
                    }
                }

                // Normal overrides
                foreach (var method in virtualMethods)
                {
                    VTableSlot slot;
                    if (method.Value.IsNewSlot)
                    {
                        slot = new VTableSlot(method.Value, _typeDef.ToTypeSig(), method.Key);
                    }
                    else if (_slotsMap.TryGetValue(method.Key, out slot))
                    {
                        Debug.Assert(!slot.MethodDef.IsFinal);
                        slot = OverridenBy(slot, method.Value);
                    }
                    else
                    {
                        slot = new VTableSlot(method.Value, _typeDef.ToTypeSig(), method.Key);
                    }

                    _slotsMap[method.Key] = slot;
                    _allSlots.Add(slot);
                }

                // MethodImpls
                foreach (var method in virtualMethods)
                {
                    foreach (var impl in method.Value.Overrides)
                    {
                        Debug.Assert(impl.MethodBody == method.Value);

                        var targetMethod = impl.MethodDeclaration.ResolveMethodDefThrow();
                        if (targetMethod.DeclaringType.IsInterface)
                        {
                            var iface     = impl.MethodDeclaration.DeclaringType.ToTypeSig();
                            var ifaceVTbl = _interfaceSlots[iface];

                            var signature  = VTableSignature.FromMethod(impl.MethodDeclaration);
                            var targetSlot = ifaceVTbl[signature];

                            // The Overrides of interface slots should directly points to the root interface slot
                            while (targetSlot.Parent != null)
                            {
                                targetSlot = (VTableSlot)targetSlot.Parent;
                            }
                            Debug.Assert(targetSlot.MethodDef.DeclaringType.IsInterface);
                            ifaceVTbl[targetSlot.Signature] = OverridenBy(targetSlot, method.Value);
                        }
                        else
                        {
                            var targetSlot = _allSlots.Single(slot => slot.MethodDef == targetMethod);
                            targetSlot = _slotsMap[targetSlot.Signature]; // Use the most derived slot
                            // Maybe implemented by above processes --- this process should take priority
                            while (targetSlot.MethodDef.DeclaringType == _typeDef)
                            {
                                targetSlot = (VTableSlot)targetSlot.Parent;
                            }
                            _slotsMap[targetSlot.Signature] = OverridenBy(targetSlot, method.Value);
                        }
                    }
                }

                var ret = new VTable(_typeDef.ToTypeSig(), _allSlots, _interfaceSlots.ToDictionary(
                                         kvp => kvp.Key, kvp => (IReadOnlyList <IVTableSlot>)kvp.Value.Values.ToList()));

                return(ret);
            }