bool IsAttributeRedundant(Attribute attribute) { var section = attribute.GetParent <AttributeSection>(); var targetDeclaration = section.Parent; if (targetDeclaration is FixedFieldDeclaration) { //Fixed fields are never null return(true); } var fieldDeclaration = targetDeclaration as FieldDeclaration; if (fieldDeclaration != null) { return(fieldDeclaration.Variables.All(variable => NullableType.IsNonNullableValueType(ctx.Resolve(variable).Type))); } var resolveResult = ctx.Resolve(targetDeclaration); var memberResolveResult = resolveResult as MemberResolveResult; if (memberResolveResult != null) { return(NullableType.IsNonNullableValueType(memberResolveResult.Member.ReturnType)); } var localResolveResult = resolveResult as LocalResolveResult; if (localResolveResult != null) { return(NullableType.IsNonNullableValueType(localResolveResult.Type)); } return(false); }
public override IType VisitParameterizedType(ParameterizedType type) { IType newType = base.VisitParameterizedType(type); if (newType != type && ConstraintsValid) { // something was changed, so we need to validate the constraints ParameterizedType newParameterizedType = newType as ParameterizedType; if (newParameterizedType != null) { // C# 4.0 spec: §4.4.4 Satisfying constraints var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; IType typeArg = newParameterizedType.GetTypeArgument(i); switch (typeArg.Kind) // void, null, and pointers cannot be used as type arguments { case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: ConstraintsValid = false; break; } if (tp.HasReferenceTypeConstraint) { if (typeArg.IsReferenceType != true) { ConstraintsValid = false; } } if (tp.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArg)) { ConstraintsValid = false; } } if (tp.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArg.GetDefinition(); if (def != null && def.IsAbstract) { ConstraintsValid = false; } ConstraintsValid &= typeArg.GetConstructors( m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.DirectBaseTypes) { IType c = constraintType.AcceptVisitor(newParameterizedType.GetSubstitution()); ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } } return(newType); }
internal static bool ValidateConstraints(ITypeParameter typeParameter, IType typeArgument, TypeVisitor substitution, CSharpConversions conversions) { switch (typeArgument.Kind) // void, null, and pointers cannot be used as type arguments { case TypeKind.Void: case TypeKind.Null: case TypeKind.Pointer: return(false); } if (typeParameter.HasReferenceTypeConstraint) { if (typeArgument.IsReferenceType != true) { return(false); } } if (typeParameter.HasValueTypeConstraint) { if (!NullableType.IsNonNullableValueType(typeArgument)) { return(false); } } if (typeParameter.HasDefaultConstructorConstraint) { ITypeDefinition def = typeArgument.GetDefinition(); if (def != null && def.IsAbstract) { return(false); } var ctors = typeArgument.GetConstructors( m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ); if (!ctors.Any()) { return(false); } } foreach (IType constraintType in typeParameter.DirectBaseTypes) { IType c = constraintType; if (substitution != null) { c = c.AcceptVisitor(substitution); } if (!conversions.IsConstraintConvertible(typeArgument, c)) { return(false); } } return(true); }
List <OperatorInfo> GetApplicableConversionOperators(IType fromType, IType toType, bool isExplicit) { // Find the candidate operators: Predicate <IUnresolvedMethod> opFilter; if (isExplicit) { opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Explicit" && m.Parameters.Count == 1; } else { opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; } var operators = NullableType.GetUnderlyingType(fromType).GetMethods(opFilter) .Concat(NullableType.GetUnderlyingType(toType).GetMethods(opFilter)).Distinct(); // Determine whether one of them is applicable: List <OperatorInfo> result = new List <OperatorInfo>(); foreach (IMethod op in operators) { IType sourceType = op.Parameters[0].Type; IType targetType = op.ReturnType; // Try if the operator is applicable: bool isApplicable; if (isExplicit) { isApplicable = IsEncompassingOrEncompassedBy(fromType, sourceType) && IsEncompassingOrEncompassedBy(targetType, toType); } else { isApplicable = IsEncompassedBy(fromType, sourceType) && IsEncompassedBy(targetType, toType); } if (isApplicable) { result.Add(new OperatorInfo(op, sourceType, targetType, false)); } // Try if the operator is applicable in lifted form: if (NullableType.IsNonNullableValueType(sourceType) && NullableType.IsNonNullableValueType(targetType)) { IType liftedSourceType = NullableType.Create(compilation, sourceType); IType liftedTargetType = NullableType.Create(compilation, targetType); if (isExplicit) { isApplicable = IsEncompassingOrEncompassedBy(fromType, liftedSourceType) && IsEncompassingOrEncompassedBy(liftedTargetType, toType); } else { isApplicable = IsEncompassedBy(fromType, liftedSourceType) && IsEncompassedBy(liftedTargetType, toType); } if (isApplicable) { result.Add(new OperatorInfo(op, liftedSourceType, liftedTargetType, true)); } } } return(result); }