Beispiel #1
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            // If implementation is public then contract can be any visibility
            if (impl.Visibility == TypeMemberVisibility.Public)
            {
                return(DifferenceType.Unknown);
            }

            // If implementation is protected or protected internal then contract must be protected or protected internal as well.
            if (impl.Visibility == TypeMemberVisibility.Family || impl.Visibility == TypeMemberVisibility.FamilyOrAssembly)
            {
                if (contract.Visibility != TypeMemberVisibility.Family && contract.Visibility != TypeMemberVisibility.FamilyOrAssembly)
                {
                    differences.AddIncompatibleDifference(this,
                                                          $"Visibility of member '{impl.FullName()}' is '{impl.Visibility}' in the {Implementation} but '{contract.Visibility}' in the {Contract}.");
                    return(DifferenceType.Changed);
                }
            }

            return(DifferenceType.Unknown);
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
                return DifferenceType.Unknown;

            bool isImplOverridable = IsOverridable(impl);
            bool isContractOverridable = IsOverridable(contract);

            /*
            //@todo: Move to a separate rule that's only run in "strict" mode. 
            if (isImplInhertiable && !isContractInheritiable)
            {
                // This is separate because it can be noisy and is generally allowed as long as it is reviewed properly.
                differences.AddIncompatibleDifference("CannotMakeMemberVirtual",
                    "Member '{0}' is virtual in the implementation but non-virtual in the contract.",
                    impl.FullName());

                return DifferenceType.Changed;
            }
            */

            if (isContractOverridable && !isImplOverridable)
            {
                differences.AddIncompatibleDifference("CannotMakeMemberNonVirtual",
                    "Member '{0}' is non-virtual in the implementation but is virtual in the contract.",
                    impl.FullName());

                return DifferenceType.Changed;
            }

            return DifferenceType.Unknown;
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            bool isImplOverridable     = IsOverridable(impl);
            bool isContractOverridable = IsOverridable(contract);

            /*
             * //@todo: Move to a separate rule that's only run in "strict" mode.
             * if (isImplInhertiable && !isContractInheritiable)
             * {
             *  // This is separate because it can be noisy and is generally allowed as long as it is reviewed properly.
             *  differences.AddIncompatibleDifference("CannotMakeMemberVirtual",
             *      "Member '{0}' is virtual in the implementation but non-virtual in the contract.",
             *      impl.FullName());
             *
             *  return DifferenceType.Changed;
             * }
             */

            if (isContractOverridable && !isImplOverridable)
            {
                differences.AddIncompatibleDifference("CannotMakeMemberNonVirtual",
                                                      $"Member '{impl.FullName()}' is non-virtual in the {Implementation} but is virtual in the {Contract}.");

                return(DifferenceType.Changed);
            }

            return(DifferenceType.Unknown);
        }
        public override DifferenceType Diff(IDifferences differences, Mappings.MemberMapping mapping)
        {
            ITypeDefinitionMember impl     = mapping[0];
            ITypeDefinitionMember contract = mapping[1];

            if (impl == null)
            {
                return(DifferenceType.Unknown);
            }

            if (contract == null && impl.IsAbstract())
            {
                // If the type is effectively sealed then it is ok to remove abstract members
                ITypeDefinition contractType = mapping.ContainingType[1];
                // We check that interfaces have the same number of members in another rule so there is no need to check that here.
                if (contractType != null && (contractType.IsEffectivelySealed() || (contractType.IsInterface && mapping.ContainingType[0].IsInterface)))
                {
                    return(DifferenceType.Unknown);
                }

                differences.AddIncompatibleDifference(this,
                                                      "Member '{0}' is abstract in the implementation but is missing in the contract.",
                                                      impl.FullName());
                return(DifferenceType.Changed);
            }
            return(DifferenceType.Unknown);
        }
Beispiel #5
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            // If implementation is public then contract can be any visibility
            if (impl.Visibility == TypeMemberVisibility.Public)
            {
                return(DifferenceType.Unknown);
            }

            // If implementation is protected then contract must be protected as well.
            if (impl.Visibility == TypeMemberVisibility.Family)
            {
                if (contract.Visibility != TypeMemberVisibility.Family)
                {
                    differences.AddIncompatibleDifference(this,
                                                          "Visibility of member '{0}' is '{1}' in the implementation but '{2}' in the contract.",
                                                          impl.FullName(), impl.Visibility, contract.Visibility);
                    return(DifferenceType.Changed);
                }
            }

            return(DifferenceType.Unknown);
        }
Beispiel #6
0
        private static ExceptionInfo ScanPlatformNotSupported(ITypeDefinitionMember item)
        {
            if (item is IMethodDefinition m)
            {
                if (m.IsPropertyOrEventAccessor())
                {
                    return(ExceptionInfo.DoesNotThrow);
                }

                return(ScanPlatformNotSupported(m));
            }
            else if (item is IPropertyDefinition p)
            {
                return(ScanPlatformNotSupported(p.Accessors));
            }
            else if (item is IEventDefinition e)
            {
                return(ScanPlatformNotSupported(e.Accessors));
            }
            else if (item is IFieldDefinition || item is ITypeDefinition)
            {
                // Ignore
                return(ExceptionInfo.DoesNotThrow);
            }
            else
            {
                throw new NotImplementedException($"Unexpected type member: {item.FullName()} ({item.GetApiKind()})");
            }
        }
Beispiel #7
0
        public override DifferenceType Diff(IDifferences differences, MemberMapping mapping)
        {
            ITypeDefinitionMember implMember     = mapping[0];
            ITypeDefinitionMember contractMember = mapping[1];
            IMethodDefinition     foundMethod;

            if (!(implMember == null && contractMember != null))
            {
                return(DifferenceType.Unknown);
            }

            // Nested types are handled separately.
            // @TODO: Events and Properties - should we consider these too (or rely on the fact that dropping one of these will also drop their accessors.)
            if (!(contractMember is IMethodDefinition || contractMember is IFieldDefinition))
            {
                return(DifferenceType.Unknown);
            }

            string incompatibeDifferenceMessage = $"Member '{contractMember.FullName()}' does not exist in the {Implementation} but it does exist in the {Contract}.";

            ITypeDefinition contractType = mapping.ContainingType[0];

            if (contractType != null)
            {
                IMethodDefinition contractMethod = contractMember as IMethodDefinition;
                if (contractMethod != null)
                {
                    // If the contract is a Explicit Interface method, we don't need to check if the method is in implementation since that will be caught by different rule.
                    if (contractMethod.IsExplicitInterfaceMethod())
                    {
                        return(DifferenceType.Unknown);
                    }



                    // It is valid to promote a member from a base type up so check to see if it member exits on a base type.
                    var lookForMethodInBaseResult = FindMatchingBase(contractType, contractMethod, out foundMethod);
                    if (lookForMethodInBaseResult == FindMethodResult.Found)
                    {
                        return(DifferenceType.Unknown);
                    }
                    if (lookForMethodInBaseResult == FindMethodResult.ReturnTypeChanged)
                    {
                        incompatibeDifferenceMessage += $" There does exist a member with return type '{foundMethod.GetReturnType().FullName()}' instead of '{contractMethod.GetReturnType().FullName()}'";
                    }
                }
            }

            differences.AddIncompatibleDifference(this, incompatibeDifferenceMessage);

            return(DifferenceType.Added);
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
                return DifferenceType.Unknown;

            if (impl.IsAbstract() && !contract.IsAbstract())
            {
                differences.AddIncompatibleDifference("CannotMakeMemberAbstract",
                    "Member '{0}' is abstract in the implementation but is not abstract in the contract.",
                    impl.FullName());

                return DifferenceType.Changed;
            }

            return DifferenceType.Unknown;
        }
 private bool IsDeprecated(ITypeDefinitionMember item)
 {
     if (item is IMethodDefinition m)
     {
         return(CheckMethodForDeprecation(m));
     }
     else if (item is IFieldDefinition || item is ITypeDefinition)
     {
         // Ignore
         return(false);
     }
     else
     {
         throw new NotImplementedException($"Unexpected type member: {item.FullName()} ({item.GetApiKind()})");
     }
 }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            if (impl.IsAbstract() && !contract.IsAbstract())
            {
                differences.AddIncompatibleDifference("CannotMakeMemberAbstract",
                                                      $"Member '{impl.FullName()}' is abstract in the {Implementation} but is not abstract in the {Contract}.");

                return(DifferenceType.Changed);
            }

            return(DifferenceType.Unknown);
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (contract != null && impl == null)
            {
                if (contract.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, $"Interface member '{contract.FullName()}' is present in the {Contract} but not in the {Implementation}.");
                    return(DifferenceType.Changed);
                }
            }

            if (impl != null && contract == null)
            {
                if (impl.ContainingTypeDefinition.IsInterface && !CanIgnoreAddedInterfaceMember(impl))
                {
                    differences.AddIncompatibleDifference(this, $"Interface member '{impl.FullName()}' is present in the {Implementation} but not in the {Contract}.");
                    return(DifferenceType.Changed);
                }
            }

            return(base.Diff(differences, impl, contract));
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (contract != null && impl == null)
            {
                if (contract.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, "Contract interface member '{0}' is not in the implementation.", contract.FullName());
                    return DifferenceType.Changed;
                }
            }

            if (impl != null && contract == null)
            {
                if (impl.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, "Implementation interface member '{0}' is not in the contract.", impl.FullName());
                    return DifferenceType.Changed;
                }
            }

            return base.Diff(differences, impl, contract);
        }
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
                return DifferenceType.Unknown;

            // If implementation is public then contract can be any visibility
            if (impl.Visibility == TypeMemberVisibility.Public)
                return DifferenceType.Unknown;

            // If implementation is protected then contract must be protected as well. 
            if (impl.Visibility == TypeMemberVisibility.Family)
            {
                if (contract.Visibility != TypeMemberVisibility.Family)
                {
                    differences.AddIncompatibleDifference(this,
                        "Visibility of member '{0}' is '{1}' in the implementation but '{2}' in the contract.",
                        impl.FullName(), impl.Visibility, contract.Visibility);
                    return DifferenceType.Changed;
                }
            }

            return DifferenceType.Unknown;
        }
Beispiel #14
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (contract != null && impl == null)
            {
                if (contract.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, "Contract interface member '{0}' is not in the implementation.", contract.FullName());
                    return(DifferenceType.Changed);
                }
            }

            if (impl != null && contract == null)
            {
                if (impl.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, "Implementation interface member '{0}' is not in the contract.", impl.FullName());
                    return(DifferenceType.Changed);
                }
            }

            return(base.Diff(differences, impl, contract));
        }