Example #1
0
        internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description)
        {
            if (!IsTargetAttribute(description.Namespace, description.Name))
            {
                return(-1);
            }

            var ctor = this.AttributeConstructor;

            // Ensure that the attribute data really has a constructor before comparing the signature.
            if (ctor is null)
            {
                return(-1);
            }

            // Lazily loaded System.Type type symbol
            TypeSymbol?lazySystemType = null;

            ImmutableArray <ParameterSymbol> parameters = ctor.Parameters;
            bool foundMatch = false;

            for (int i = 0; i < description.Signatures.Length; i++)
            {
                byte[] targetSignature = description.Signatures[i];
                if (targetSignature[0] != (byte)SignatureAttributes.Instance)
                {
                    continue;
                }

                byte parameterCount = targetSignature[1];
                if (parameterCount != parameters.Length)
                {
                    continue;
                }

                if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void)
                {
                    continue;
                }

                foundMatch = (targetSignature.Length == 3);
                int k = 0;
                for (int j = 3; j < targetSignature.Length; j++)
                {
                    if (k >= parameters.Length)
                    {
                        break;
                    }

                    TypeSymbol  parameterType = parameters[k].Type;
                    SpecialType specType      = parameterType.SpecialType;
                    byte        targetType    = targetSignature[j];

                    if (targetType == (byte)SignatureTypeCode.TypeHandle)
                    {
                        j++;

                        if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType)
                        {
                            foundMatch = false;
                            break;
                        }

                        var namedType = (NamedTypeSymbol)parameterType;
                        AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[j]];

                        // Compare name and containing symbol name. Uses HasNameQualifier
                        // extension method to avoid string allocations.
                        if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) ||
                            !namedType.HasNameQualifier(targetInfo.Namespace))
                        {
                            foundMatch = false;
                            break;
                        }

                        targetType = (byte)targetInfo.Underlying;

                        if (parameterType.IsEnumType())
                        {
                            specType = parameterType.GetEnumUnderlyingType() !.SpecialType;
                        }
                    }
                    else if (parameterType.IsArray())
                    {
                        specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType;
                    }

                    switch (targetType)
                    {
                    case (byte)SignatureTypeCode.Boolean:
                        foundMatch = specType == SpecialType.System_Boolean;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Char:
                        foundMatch = specType == SpecialType.System_Char;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.SByte:
                        foundMatch = specType == SpecialType.System_SByte;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Byte:
                        foundMatch = specType == SpecialType.System_Byte;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int16:
                        foundMatch = specType == SpecialType.System_Int16;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt16:
                        foundMatch = specType == SpecialType.System_UInt16;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int32:
                        foundMatch = specType == SpecialType.System_Int32;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt32:
                        foundMatch = specType == SpecialType.System_UInt32;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Int64:
                        foundMatch = specType == SpecialType.System_Int64;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt64:
                        foundMatch = specType == SpecialType.System_UInt64;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Single:
                        foundMatch = specType == SpecialType.System_Single;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Double:
                        foundMatch = specType == SpecialType.System_Double;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.String:
                        foundMatch = specType == SpecialType.System_String;
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.Object:
                        foundMatch = specType == SpecialType.System_Object;
                        k         += 1;
                        break;

                    case (byte)SerializationTypeCode.Type:
                        if (lazySystemType is null)
                        {
                            lazySystemType = GetSystemType(targetSymbol);
                        }

                        foundMatch = TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything2);
                        k         += 1;
                        break;

                    case (byte)SignatureTypeCode.SZArray:
                        // Skip over and check the next byte
                        foundMatch = parameterType.IsArray();
                        break;

                    default:
                        return(-1);
                    }

                    if (!foundMatch)
                    {
                        break;
                    }
                }

                if (foundMatch)
                {
                    return(i);
                }
            }

            Debug.Assert(!foundMatch);
            return(-1);
        }
Example #2
0
        internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description)
        {
            if (!IsTargetAttribute(description.Namespace, description.Name))
            {
                return(-1);
            }

            var ctor = this.AttributeConstructor;

            // Ensure that the attribute data really has a constructor before comparing the signature.
            if (ctor is null)
            {
                return(-1);
            }

            // Lazily loaded System.Type type symbol
            TypeSymbol?lazySystemType = null;

            ImmutableArray <ParameterSymbol> parameters = ctor.Parameters;

            for (int signatureIndex = 0; signatureIndex < description.Signatures.Length; signatureIndex++)
            {
                byte[] targetSignature = description.Signatures[signatureIndex];

                if (matches(targetSignature, parameters, ref lazySystemType))
                {
                    return(signatureIndex);
                }
            }

            return(-1);

            bool matches(byte[] targetSignature, ImmutableArray <ParameterSymbol> parameters, ref TypeSymbol?lazySystemType)
            {
                if (targetSignature[0] != (byte)SignatureAttributes.Instance)
                {
                    return(false);
                }

                byte parameterCount = targetSignature[1];

                if (parameterCount != parameters.Length)
                {
                    return(false);
                }

                if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void)
                {
                    return(false);
                }

                int parameterIndex = 0;

                for (int signatureByteIndex = 3; signatureByteIndex < targetSignature.Length; signatureByteIndex++)
                {
                    if (parameterIndex >= parameters.Length)
                    {
                        return(false);
                    }

                    TypeSymbol  parameterType = parameters[parameterIndex].Type;
                    SpecialType specType      = parameterType.SpecialType;
                    byte        targetType    = targetSignature[signatureByteIndex];

                    if (targetType == (byte)SignatureTypeCode.TypeHandle)
                    {
                        signatureByteIndex++;

                        if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType)
                        {
                            return(false);
                        }

                        var namedType = (NamedTypeSymbol)parameterType;
                        AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[signatureByteIndex]];

                        // Compare name and containing symbol name. Uses HasNameQualifier
                        // extension method to avoid string allocations.
                        if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) ||
                            !namedType.HasNameQualifier(targetInfo.Namespace))
                        {
                            return(false);
                        }

                        targetType = (byte)targetInfo.Underlying;

                        if (parameterType.IsEnumType())
                        {
                            specType = parameterType.GetEnumUnderlyingType() !.SpecialType;
                        }
                    }
                    else if (targetType != (byte)SignatureTypeCode.SZArray && parameterType.IsArray())
                    {
                        if (targetSignature[signatureByteIndex - 1] != (byte)SignatureTypeCode.SZArray)
                        {
                            return(false);
                        }

                        specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType;
                    }

                    switch (targetType)
                    {
                    case (byte)SignatureTypeCode.Boolean:
                        if (specType != SpecialType.System_Boolean)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Char:
                        if (specType != SpecialType.System_Char)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.SByte:
                        if (specType != SpecialType.System_SByte)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Byte:
                        if (specType != SpecialType.System_Byte)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Int16:
                        if (specType != SpecialType.System_Int16)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt16:
                        if (specType != SpecialType.System_UInt16)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Int32:
                        if (specType != SpecialType.System_Int32)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt32:
                        if (specType != SpecialType.System_UInt32)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Int64:
                        if (specType != SpecialType.System_Int64)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.UInt64:
                        if (specType != SpecialType.System_UInt64)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Single:
                        if (specType != SpecialType.System_Single)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Double:
                        if (specType != SpecialType.System_Double)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.String:
                        if (specType != SpecialType.System_String)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.Object:
                        if (specType != SpecialType.System_Object)
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SerializationTypeCode.Type:
                        lazySystemType ??= GetSystemType(targetSymbol);

                        if (!TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything))
                        {
                            return(false);
                        }
                        parameterIndex += 1;
                        break;

                    case (byte)SignatureTypeCode.SZArray:
                        // Skip over and check the next byte
                        if (!parameterType.IsArray())
                        {
                            return(false);
                        }
                        break;

                    default:
                        return(false);
                    }
                }

                return(true);
            }
        }