internal static bool CanAssignTo(this AttributeArgumentSyntax @this, ITypeSymbol target, SemanticModel model)
        {
            //See https://github.com/nunit/nunit/blob/f16d12d6fa9e5c879601ad57b4b24ec805c66054/src/NUnitFramework/framework/Attributes/TestCaseAttribute.cs#L396
            //for the reasoning behind this implementation.
            Optional <object> possibleConstantValue = model.GetConstantValue(@this.Expression);
            object            argumentValue         = null;

            if (possibleConstantValue.HasValue)
            {
                argumentValue = possibleConstantValue.Value;
            }
            TypeInfo    sourceTypeInfo = model.GetTypeInfo(@this.Expression);
            ITypeSymbol argumentType   = sourceTypeInfo.Type;

            if (argumentType == null)
            {
                return(target.IsReferenceType ||
                       target.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T);
            }
            else
            {
                var targetType = GetTargetType(target);
                if (targetType.IsAssignableFrom(argumentType))
                {
                    return(true);
                }
                else
                {
                    var canConvert = false;

                    if (targetType.SpecialType == SpecialType.System_Int16 || targetType.SpecialType == SpecialType.System_Byte ||
                        targetType.SpecialType == SpecialType.System_Int64 ||
                        targetType.SpecialType == SpecialType.System_SByte || targetType.SpecialType == SpecialType.System_Double)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_Int32;
                    }
                    else if (targetType.SpecialType == SpecialType.System_Decimal)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_Double ||
                                     argumentType.SpecialType == SpecialType.System_String ||
                                     argumentType.SpecialType == SpecialType.System_Int32;
                    }
                    else if (targetType.SpecialType == SpecialType.System_DateTime)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_String;
                    }

                    if (canConvert)
                    {
                        return(AttributeArgumentSyntaxExtensions.TryChangeType(targetType, argumentValue));
                    }
                    else if (argumentType.SpecialType == SpecialType.System_String &&
                             model.Compilation.GetTypeByMetadataName(typeof(TimeSpan).FullName).IsAssignableFrom(targetType))
                    {
                        canConvert = TimeSpan.TryParse(argumentValue as string, out _);
                    }

                    return(canConvert);
                }
            }
        }
Beispiel #2
0
        internal static bool CanAssignTo(this AttributeArgumentSyntax @this, ITypeSymbol target, SemanticModel model)
        {
            //See https://github.com/nunit/nunit/blob/master/src/NUnitFramework/framework/Attributes/TestCaseAttribute.cs#L363
            //for the reasoning behind this implementation.
            object argumentValue = null;

            if (@this.Expression is LiteralExpressionSyntax)
            {
                argumentValue = (@this.Expression as LiteralExpressionSyntax).Token.Value;
            }

            TypeInfo    sourceTypeInfo = model.GetTypeInfo(@this.Expression);
            ITypeSymbol argumentType   = sourceTypeInfo.Type;

            if (sourceTypeInfo.Type == null)
            {
                return(target.IsReferenceType ||
                       target.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T);
            }
            else
            {
                var targetType = GetTargetType(target);
                if (targetType.IsAssignableFrom(argumentType))
                {
                    return(true);
                }
                else
                {
                    var canConvert = false;

                    if (targetType.SpecialType == SpecialType.System_Int16 || targetType.SpecialType == SpecialType.System_Byte ||
                        targetType.SpecialType == SpecialType.System_SByte || targetType.SpecialType == SpecialType.System_Double)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_Int32;
                    }
                    else if (targetType.SpecialType == SpecialType.System_Decimal)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_Double ||
                                     argumentType.SpecialType == SpecialType.System_String ||
                                     argumentType.SpecialType == SpecialType.System_Int32;
                    }
                    else if (targetType.SpecialType == SpecialType.System_DateTime)
                    {
                        canConvert = argumentType.SpecialType == SpecialType.System_String;
                    }

                    if (canConvert)
                    {
                        return(AttributeArgumentSyntaxExtensions.TryChangeType(targetType, argumentValue));
                    }
                    else if (argumentType.SpecialType == SpecialType.System_String &&
                             model.Compilation.GetTypeByMetadataName(typeof(TimeSpan).FullName).IsAssignableFrom(targetType))
                    {
                        var outValue = default(TimeSpan);
                        canConvert = TimeSpan.TryParse(argumentValue as string, out outValue);
                    }

                    return(canConvert);
                }
            }
        }