예제 #1
0
        internal static IEnumerable <DerivedTypesEntryNode> FindDerivedTypes(AssemblyList list, ITypeDefinition type,
                                                                             PEFile[] assemblies, CancellationToken cancellationToken)
        {
            var definitionMetadata = type.ParentModule.PEFile.Metadata;
            var metadataToken      = (SRM.TypeDefinitionHandle)type.MetadataToken;

            foreach (var module in assemblies)
            {
                var metadata = module.Metadata;
                var assembly = (MetadataModule)module.GetTypeSystemOrNull().MainModule;
                foreach (var h in metadata.TypeDefinitions)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var td = metadata.GetTypeDefinition(h);
                    foreach (var iface in td.GetInterfaceImplementations())
                    {
                        var ifaceImpl = metadata.GetInterfaceImplementation(iface);
                        if (!ifaceImpl.Interface.IsNil && IsSameType(metadata, ifaceImpl.Interface, definitionMetadata, metadataToken))
                        {
                            yield return(new DerivedTypesEntryNode(list, assembly.GetDefinition(h)));
                        }
                    }
                    SRM.EntityHandle baseType = td.GetBaseTypeOrNil();
                    if (!baseType.IsNil && IsSameType(metadata, baseType, definitionMetadata, metadataToken))
                    {
                        yield return(new DerivedTypesEntryNode(list, assembly.GetDefinition(h)));
                    }
                }
            }
            yield break;
        }
예제 #2
0
        public virtual CodeMappingInfo GetCodeMappingInfo(PEFile module, SRM.EntityHandle member)
        {
            var parts     = new Dictionary <SRM.MethodDefinitionHandle, SRM.MethodDefinitionHandle[]>();
            var locations = new Dictionary <SRM.EntityHandle, SRM.MethodDefinitionHandle>();

            var declaringType = member.GetDeclaringType(module.Metadata);

            if (declaringType.IsNil && member.Kind == SRM.HandleKind.TypeDefinition)
            {
                declaringType = (SRM.TypeDefinitionHandle)member;
            }

            return(new CodeMappingInfo(module, declaringType));
        }
예제 #3
0
        bool?IsReferenceType(SRM.MetadataReader reader, SRM.EntityHandle handle, byte rawTypeKind)
        {
            switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind))
            {
            case SRM.SignatureTypeKind.ValueType:
                return(false);

            case SRM.SignatureTypeKind.Class:
                return(true);

            default:
                return(null);
            }
        }
예제 #4
0
 static bool IsSameType(SRM.MetadataReader referenceMetadata, SRM.EntityHandle typeRef,
                        SRM.MetadataReader definitionMetadata, SRM.TypeDefinitionHandle typeDef)
 {
     // FullName contains only namespace, name and type parameter count, therefore this should suffice.
     return(typeRef.GetFullTypeName(referenceMetadata) == typeDef.GetFullTypeName(definitionMetadata));
 }
예제 #5
0
        private uint CalculateMethodDefTreatmentAndRowId(MethodDefinitionHandle methodDef)
        {
            MethodDefTreatment treatment = MethodDefTreatment.Implementation;

            TypeDefinitionHandle parentTypeDef = GetDeclaringType(methodDef);
            TypeAttributes       parentFlags   = TypeDefTable.GetFlags(parentTypeDef);

            if ((parentFlags & TypeAttributes.WindowsRuntime) != 0)
            {
                if (IsClrImplementationType(parentTypeDef))
                {
                    treatment = MethodDefTreatment.Implementation;
                }
                else if (parentFlags.IsNested())
                {
                    treatment = MethodDefTreatment.Implementation;
                }
                else if ((parentFlags & TypeAttributes.Interface) != 0)
                {
                    treatment = MethodDefTreatment.InterfaceMethod;
                }
                else if (_metadataKind == MetadataKind.ManagedWindowsMetadata && (parentFlags & TypeAttributes.Public) == 0)
                {
                    treatment = MethodDefTreatment.Implementation;
                }
                else
                {
                    treatment = MethodDefTreatment.Other;

                    var parentBaseType = TypeDefTable.GetExtends(parentTypeDef);
                    if (parentBaseType.Kind == HandleKind.TypeReference)
                    {
                        switch (GetSpecialTypeRefTreatment((TypeReferenceHandle)parentBaseType))
                        {
                        case TypeRefTreatment.SystemAttribute:
                            treatment = MethodDefTreatment.AttributeMethod;
                            break;

                        case TypeRefTreatment.SystemDelegate:
                            treatment = MethodDefTreatment.DelegateMethod | MethodDefTreatment.MarkPublicFlag;
                            break;
                        }
                    }
                }
            }

            if (treatment == MethodDefTreatment.Other)
            {
                // we want to hide the method if it implements
                // only redirected interfaces
                // We also want to check if the methodImpl is IClosable.Close,
                // so we can change the name
                bool seenRedirectedInterfaces    = false;
                bool seenNonRedirectedInterfaces = false;

                bool isIClosableClose = false;

                foreach (var methodImplHandle in new MethodImplementationHandleCollection(this, parentTypeDef))
                {
                    MethodImplementation methodImpl = GetMethodImplementation(methodImplHandle);
                    if (methodImpl.MethodBody == methodDef)
                    {
                        EntityHandle declaration = methodImpl.MethodDeclaration;

                        // See if this MethodImpl implements a redirected interface
                        // In WinMD, MethodImpl will always use MemberRef and TypeRefs to refer to redirected interfaces,
                        // even if they are in the same module.
                        if (declaration.Kind == HandleKind.MemberReference &&
                            ImplementsRedirectedInterface((MemberReferenceHandle)declaration, out isIClosableClose))
                        {
                            seenRedirectedInterfaces = true;
                            if (isIClosableClose)
                            {
                                // This method implements IClosable.Close
                                // Let's rename to IDisposable later
                                // Once we know this implements IClosable.Close, we are done
                                // looking
                                break;
                            }
                        }
                        else
                        {
                            // Now we know this implements a non-redirected interface
                            // But we need to keep looking, just in case we got a methodimpl that
                            // implements the IClosable.Close method and needs to be renamed
                            seenNonRedirectedInterfaces = true;
                        }
                    }
                }

                if (isIClosableClose)
                {
                    treatment = MethodDefTreatment.DisposeMethod;
                }
                else if (seenRedirectedInterfaces && !seenNonRedirectedInterfaces)
                {
                    // Only hide if all the interfaces implemented are redirected
                    treatment = MethodDefTreatment.HiddenInterfaceImplementation;
                }
            }

            // If treatment is other, then this is a non-managed WinRT runtime class definition
            // Find out about various bits that we apply via attributes and name parsing
            if (treatment == MethodDefTreatment.Other)
            {
                treatment |= GetMethodTreatmentFromCustomAttributes(methodDef);
            }

            return(TreatmentAndRowId((byte)treatment, methodDef.RowId));
        }
예제 #6
0
        internal uint CalculateTypeDefTreatmentAndRowId(TypeDefinitionHandle handle)
        {
            Debug.Assert(_metadataKind != MetadataKind.Ecma335);

            TypeDefTreatment treatment;

            TypeAttributes flags   = TypeDefTable.GetFlags(handle);
            EntityHandle   extends = TypeDefTable.GetExtends(handle);

            if ((flags & TypeAttributes.WindowsRuntime) != 0)
            {
                if (_metadataKind == MetadataKind.WindowsMetadata)
                {
                    treatment = GetWellKnownTypeDefinitionTreatment(handle);
                    if (treatment != TypeDefTreatment.None)
                    {
                        return(TreatmentAndRowId((byte)treatment, handle.RowId));
                    }

                    // Is this an attribute?
                    if (extends.Kind == HandleKind.TypeReference && IsSystemAttribute((TypeReferenceHandle)extends))
                    {
                        treatment = TypeDefTreatment.NormalAttribute;
                    }
                    else
                    {
                        treatment = TypeDefTreatment.NormalNonAttribute;
                    }
                }
                else if (_metadataKind == MetadataKind.ManagedWindowsMetadata && NeedsWinRTPrefix(flags, extends))
                {
                    // WinMDExp emits two versions of RuntimeClasses and Enums:
                    //
                    //    public class Foo {}            // the WinRT reference class
                    //    internal class <CLR>Foo {}     // the implementation class that we want WinRT consumers to ignore
                    //
                    // The adapter's job is to undo WinMDExp's transformations. I.e. turn the above into:
                    //
                    //    internal class <WinRT>Foo {}   // the WinRT reference class that we want CLR consumers to ignore
                    //    public class Foo {}            // the implementation class
                    //
                    // We only add the <WinRT> prefix here since the WinRT view is the only view that is marked WindowsRuntime
                    // De-mangling the CLR name is done below.


                    // tomat: The CLR adapter implements a back-compat quirk: Enums exported with an older WinMDExp have only one version
                    // not marked with tdSpecialName. These enums should *not* be mangled and flipped to private.
                    // We don't implement this flag since the WinMDs produced by the older WinMDExp are not used in the wild.

                    treatment = TypeDefTreatment.PrefixWinRTName;
                }
                else
                {
                    treatment = TypeDefTreatment.None;
                }

                // Scan through Custom Attributes on type, looking for interesting bits. We only
                // need to do this for RuntimeClasses
                if ((treatment == TypeDefTreatment.PrefixWinRTName || treatment == TypeDefTreatment.NormalNonAttribute))
                {
                    if ((flags & TypeAttributes.Interface) == 0 &&
                        HasAttribute(handle, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute"))
                    {
                        treatment |= TypeDefTreatment.MarkAbstractFlag;
                    }
                }
            }
            else if (_metadataKind == MetadataKind.ManagedWindowsMetadata && IsClrImplementationType(handle))
            {
                // <CLR> implementation classes are not marked WindowsRuntime, but still need to be modified
                // by the adapter.
                treatment = TypeDefTreatment.UnmangleWinRTName;
            }
            else
            {
                treatment = TypeDefTreatment.None;
            }

            return(TreatmentAndRowId((byte)treatment, handle.RowId));
        }