private bool EqualsType(ITypeSignature x, ITypeSignature y, ICodeNode xGenericContext = null)
        {
            if (x == y)
            {
                return(true);
            }

            if (x == null || y == null)
            {
                return(false);
            }

            switch (x.ElementCode)
            {
            case TypeElementCode.Array:
            {
                if (y.ElementCode != TypeElementCode.Array)
                {
                    return(false);
                }

                if (!SignatureComparer.EqualsArrayDimensions(x.ArrayDimensions, y.ArrayDimensions))
                {
                    return(false);
                }

                if (!EqualsType(x.ElementType, y.ElementType, xGenericContext))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.ByRef:
            {
                if (y.ElementCode != TypeElementCode.ByRef)
                {
                    return(false);
                }

                if (!EqualsType(x.ElementType, y.ElementType, xGenericContext))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.CustomModifier:
            {
                if (y.ElementCode != TypeElementCode.CustomModifier)
                {
                    return(false);
                }

                CustomModifierType xModifierType;
                var xModifier = x.GetCustomModifier(out xModifierType);

                CustomModifierType yModifierType;
                var yModifier = y.GetCustomModifier(out yModifierType);

                if (xModifierType != yModifierType)
                {
                    return(false);
                }

                if (!EqualsType(x.ElementType, y.ElementType, xGenericContext))
                {
                    return(false);
                }

                if (!EqualsType(xModifier, yModifier))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.FunctionPointer:
            {
                if (y.ElementCode != TypeElementCode.FunctionPointer)
                {
                    return(false);
                }

                if (!EqualsMethod(x.GetFunctionPointer(), y.GetFunctionPointer()))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.GenericParameter:
            {
                bool xIsMethod;
                int  xPosition;
                x.GetGenericParameter(out xIsMethod, out xPosition);

                if (xGenericContext != null)
                {
                    var xGenericType = xGenericContext.GetGenericArgument(xIsMethod, xPosition);
                    if (xGenericType != null)
                    {
                        return(EqualsType(xGenericType, y));
                    }
                }

                if (y.ElementCode != TypeElementCode.GenericParameter)
                {
                    return(false);
                }

                bool yIsMethod;
                int  yPosition;
                y.GetGenericParameter(out yIsMethod, out yPosition);

                if (xIsMethod != yIsMethod)
                {
                    return(false);
                }

                if (xPosition != yPosition)
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.GenericType:
            {
                if (y.ElementCode != TypeElementCode.GenericType)
                {
                    return(false);
                }

                if (!EqualsType(x.DeclaringType, y.DeclaringType))
                {
                    return(false);
                }

                if (!EqualsTypes(x.GenericArguments, y.GenericArguments, xGenericContext))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.Pinned:
            {
                if (y.ElementCode != TypeElementCode.Pinned)
                {
                    return(false);
                }

                if (!EqualsType(x.ElementType, y.ElementType, xGenericContext))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.Pointer:
            {
                if (y.ElementCode != TypeElementCode.Pointer)
                {
                    return(false);
                }

                if (!EqualsType(x.ElementType, y.ElementType, xGenericContext))
                {
                    return(false);
                }

                return(true);
            }

            case TypeElementCode.DeclaringType:
            {
                if (x.Name != y.Name)
                {
                    return(false);
                }

                if (x.Namespace != y.Namespace)
                {
                    return(false);
                }

                if (!EqualsTypeOwner(x.Owner, y.Owner))
                {
                    return(false);
                }

                return(true);
            }

            default:
                throw new NotImplementedException();
            }
        }
        protected virtual IType ResolveType(ITypeSignature typeSig, IModule context, ICodeNode genericContext)
        {
            switch (typeSig.ElementCode)
            {
            case TypeElementCode.Array:
            {
                var elementType = ResolveType(typeSig.ElementType, context, genericContext);
                if (elementType == null)
                {
                    return(null);
                }

                return(elementType.MakeArrayType(typeSig.ArrayDimensions));
            }

            case TypeElementCode.ByRef:
            {
                var elementType = ResolveType(typeSig.ElementType, context, genericContext);
                if (elementType == null)
                {
                    return(null);
                }

                return(elementType.MakeByRefType());
            }

            case TypeElementCode.CustomModifier:
            {
                var elementType = ResolveType(typeSig.ElementType, context, genericContext);
                if (elementType == null)
                {
                    return(null);
                }

                CustomModifierType modifierType;
                var modifierSig = typeSig.GetCustomModifier(out modifierType);
                var modifier    = ResolveType(modifierSig, context, genericContext);

                return(elementType.MakeCustomModifierType(modifier, modifierType));
            }

            case TypeElementCode.FunctionPointer:
            {
                var callSite = ResolveCallSite(typeSig.GetFunctionPointer(), context, genericContext);
                return(MakeFunctionPointerType(callSite));
            }

            case TypeElementCode.GenericParameter:
            {
                bool isMethod;
                int  position;
                typeSig.GetGenericParameter(out isMethod, out position);

                if (genericContext != null)
                {
                    var type = genericContext.GetGenericArgument(isMethod, position);
                    if (type != null)
                    {
                        return(type);
                    }
                }

                return(MakeGenericParameterType(isMethod, position));
            }

            case TypeElementCode.GenericType:
            {
                var declaringType = ResolveType(typeSig.DeclaringType, context, genericContext);
                if (declaringType == null)
                {
                    return(null);
                }

                var genericArgumentSigs = typeSig.GenericArguments;
                if (genericArgumentSigs.Count == 0)
                {
                    return(declaringType);
                }

                var genericArguments = ResolveTypes(genericArgumentSigs, context, genericContext);
                if (genericArguments == null)
                {
                    return(null);
                }

                return(declaringType.MakeGenericType(genericArguments));
            }

            case TypeElementCode.Pinned:
            {
                var elementType = ResolveType(typeSig.ElementType, context, genericContext);
                if (elementType == null)
                {
                    return(null);
                }

                return(elementType.MakePinnedType());
            }

            case TypeElementCode.Pointer:
            {
                var elementType = ResolveType(typeSig.ElementType, context, genericContext);
                if (elementType == null)
                {
                    return(null);
                }

                return(elementType.MakePointerType());
            }

            case TypeElementCode.DeclaringType:
            {
                return(ResolveDeclaringType(typeSig, context));
            }

            default:
                throw new NotImplementedException();
            }
        }