예제 #1
0
        private static bool TryChangeType(ITypeSymbol targetType, object argumentValue)
        {
            var targetReflectionType = Type.GetType(
                AttributeArgumentSyntaxExtensions.GetFullName(targetType), false);

            if (targetReflectionType != null)
            {
                try
                {
                    Convert.ChangeType(argumentValue, targetReflectionType, CultureInfo.InvariantCulture);
                    return(true);
                }
                catch (InvalidCastException)
                {
                    return(false);
                }
                catch (FormatException)
                {
                    return(false);
                }
                catch (OverflowException)
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
        private static Type GetTargetReflectionType(ITypeSymbol targetType)
        {
            string assembly = ", " + targetType.ContainingAssembly.Identity.ToString();
            string typeName = AttributeArgumentSyntaxExtensions.GetQualifiedTypeName(targetType);

            // First try to get type using assembly-qualified name, and if that fails try to get type
            // using only the type name qualified by its namespace.
            // This is a hacky attempt to make it work for types that are forwarded in .NET Core, e.g.
            // Double which exists in the System.Runtime assembly at design time and in
            // System.Private.CorLib at runtime, so targetType.ContainingAssembly will denote the wrong
            // assembly, System.Runtime. See e.g. the following comment
            // https://github.com/dotnet/roslyn/issues/16211#issuecomment-373084209
            var targetReflectionType = Type.GetType(typeName + assembly, false) ?? Type.GetType(typeName, false);

            return(targetReflectionType);
        }
        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);
                }
            }
        }
예제 #4
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);
                }
            }
        }